Fix wrapper using custom ClassLoader

This commit is contained in:
Johannes Frohnmeyer 2022-01-19 23:44:06 +01:00
parent 9b9284910a
commit 9df4a14def
Signed by: Johannes
GPG Key ID: E76429612C2929F4
4 changed files with 74 additions and 16 deletions

View File

@ -9,19 +9,17 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class Wrapper {
private static final Path INCEPTUM_LIB_DIR = MetaHolder.BASE_PATH.resolve("libraries/io/gitlab/jfronny/inceptum/Inceptum");
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, URISyntaxException, NoSuchFieldException {
System.out.println("Inceptum Wrapper v" + MetaHolder.VERSION.version + " (" + MetaHolder.VERSION.flavor + ")");
ConfigHolder.load();
if (!Files.exists(INCEPTUM_LIB_DIR)) downloadLatest();
@ -37,7 +35,7 @@ public class Wrapper {
newArgs[0] = "wrapper";
System.arraycopy(args, 0, newArgs, 1, args.length);
System.out.println("Starting Inceptum ClassLoader");
WrapperStrap.switchEnv(localBinary.get().toUri().toURL(),
WrapperStrap.switchEnv(localBinary.get(),
"io.gitlab.jfronny.inceptum.Inceptum",
newArgs);
}

View File

@ -0,0 +1,58 @@
package io.gitlab.jfronny.inceptum;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
public class WrapperClassLoader extends ClassLoader {
private final Path source;
public WrapperClassLoader(Path zipArchive) throws IOException, URISyntaxException {
super(null);
this.source = Files.isDirectory(zipArchive) ? zipArchive : Utils.openZipFile(zipArchive, false).getPath("");
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Path path = getPath(name);
if (!Files.exists(path)) return WrapperStrap.SYSTEM_LOADER.loadClass(name);
byte[] clazz;
try {
clazz = Files.readAllBytes(path);
} catch (IOException e) {
throw new ClassNotFoundException("Could not find class", e);
}
return defineClass(name, clazz, 0, clazz.length);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (!Files.exists(getPath(name)) || name.equals("io.gitlab.jfronny.inceptum.WrapperStrap")) return WrapperStrap.SYSTEM_LOADER.loadClass(name);
synchronized(this.getClassLoadingLock(name)) {
Class<?> c = this.findLoadedClass(name);
if (c == null) c = this.findClass(name);
if (resolve) this.resolveClass(c);
return c;
}
}
@Override
public URL getResource(String name) {
Path p = source.resolve(name);
if (!Files.exists(p)) return WrapperStrap.SYSTEM_LOADER.getResource(name);
try {
return p.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("Could not get resource", e);
}
}
private Path getPath(String className) {
return source.resolve(className.replace('.', '/') + ".class");
}
}

View File

@ -1,23 +1,24 @@
package io.gitlab.jfronny.inceptum;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URISyntaxException;
import java.nio.file.Path;
public class WrapperStrap {
private static final ClassLoader cl = Thread.currentThread().getContextClassLoader();
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
public static final ClassLoader SYSTEM_LOADER = ClassLoader.getSystemClassLoader();
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, URISyntaxException, NoSuchFieldException {
System.out.println("Starting Inceptum Wrapper ClassLoader");
switchEnv(WrapperStrap.class.getProtectionDomain().getCodeSource().getLocation(),
switchEnv(Path.of(WrapperStrap.class.getProtectionDomain().getCodeSource().getLocation().getPath()),
"io.gitlab.jfronny.inceptum.Wrapper",
args);
}
public static void switchEnv(URL url, String mainClass, String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ClassLoader cl = new URLClassLoader(new URL[] {url}, WrapperStrap.cl);
Thread.currentThread().setContextClassLoader(cl);
cl
.loadClass(mainClass)
public static void switchEnv(Path jar, String mainClass, String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, URISyntaxException, NoSuchFieldException {
ClassLoader loader = new WrapperClassLoader(jar);
Thread.currentThread().setContextClassLoader(loader);
loader.loadClass(mainClass)
.getDeclaredMethod("main", String[].class)
.invoke(null, new Object[] {args});
}

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.inceptum.util;
import io.gitlab.jfronny.inceptum.WrapperStrap;
import io.gitlab.jfronny.inceptum.gson.GsonHolder;
import io.gitlab.jfronny.inceptum.model.OSType;
import io.gitlab.jfronny.inceptum.util.lambda.ThrowingConsumer;
@ -250,6 +251,6 @@ public class Utils {
public static FileSystem openZipFile(Path zip, boolean create) throws IOException, URISyntaxException {
URI fileUri = zip.toUri();
return FileSystems.newFileSystem(new URI("jar:" + fileUri.getScheme(), fileUri.getPath(), null), create ? Map.of("create", "true") : Map.of());
return FileSystems.newFileSystem(new URI("jar:" + fileUri.getScheme(), fileUri.getPath(), null), create ? Map.of("create", "true") : Map.of(), WrapperStrap.SYSTEM_LOADER);
}
}