Try to fix class loading

This commit is contained in:
TheKodeToad 2024-05-24 16:16:50 +01:00
parent 6fd6c3ab34
commit 4ec31a0082
4 changed files with 135 additions and 72 deletions

View file

@ -12,7 +12,7 @@ import java.util.*;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.ecorous.esnesnon.nonsense.loader.api.Loader; import org.ecorous.esnesnon.nonsense.loader.api.Loader;
import org.ecorous.esnesnon.nonsense.loader.api.env.Env; import org.ecorous.esnesnon.nonsense.loader.api.env.Env;
import org.ecorous.esnesnon.nonsense.loader.impl.launch.MixinClassloader; import org.ecorous.esnesnon.nonsense.loader.impl.launch.MixinClassLoader;
import org.ecorous.esnesnon.nonsense.loader.impl.plugin.NonsensePlugin; import org.ecorous.esnesnon.nonsense.loader.impl.plugin.NonsensePlugin;
import lombok.Getter; import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -40,14 +40,14 @@ public class LoaderImpl implements Loader {
private final Path gameDir, configDir, modsDir; private final Path gameDir, configDir, modsDir;
@Getter @Getter
private final MixinClassloader classloader; private final MixinClassLoader classloader;
@Getter @Getter
private final Gson gson = new Gson(); private final Gson gson = new Gson();
private LoaderImpl(String[] args, Env env) { private LoaderImpl(String[] args, Env env) {
instance = this; instance = this;
this.classloader = (MixinClassloader) this.getClass().getClassLoader(); this.classloader = (MixinClassLoader) this.getClass().getClassLoader();
this.args = args; this.args = args;
this.env = env; this.env = env;

View file

@ -1,17 +1,9 @@
package org.ecorous.esnesnon.nonsense.loader.impl.launch; package org.ecorous.esnesnon.nonsense.loader.impl.launch;
import java.io.File;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.ecorous.esnesnon.nonsense.loader.api.env.Env; import org.ecorous.esnesnon.nonsense.loader.api.env.Env;
@ -23,8 +15,7 @@ import org.spongepowered.asm.service.IPropertyKey;
public class Launcher { public class Launcher {
@Getter @Getter
private final MixinClassloader targetClassLoader; private final MixinClassLoader targetClassLoader;
private final List<Path> classPath;
@Getter @Getter
private static Launcher instance; private static Launcher instance;
@ -45,15 +36,10 @@ public class Launcher {
} }
instance = this; instance = this;
this.env = env; this.env = env;
classPath = Arrays.stream(System.getProperty("java.class.path").split(File.pathSeparator)).filter(s -> !"*".equals(s)).map(Paths::get).toList(); targetClassLoader = new MixinClassLoader();
targetClassLoader = new MixinClassloader(classPath.stream().map(Path::toUri).map((URI uri) -> { targetClassLoader.excludePackage("org.apache.logging");
try { targetClassLoader.excludePackage("org.ecorous.esnesnon.nonsense.loader.impl.launch");
return uri.toURL(); targetClassLoader.excludePackage("org.ecorous.esnesnon.nonsense.loader.api.env");
} catch (MalformedURLException e) {
// TODO
throw new RuntimeException(e);
}
}).toArray(URL[]::new), this.getClass().getClassLoader());
Thread.currentThread().setContextClassLoader(targetClassLoader); Thread.currentThread().setContextClassLoader(targetClassLoader);

View file

@ -0,0 +1,127 @@
package org.ecorous.esnesnon.nonsense.loader.impl.launch;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
public class MixinClassLoader extends URLClassLoader {
private static final ClassLoader SYSTEM = ClassLoader.getSystemClassLoader();
private final List<String> exclusions = new ArrayList<>();
static {
registerAsParallelCapable();
}
public MixinClassLoader() {
super(new URL[0], null);
excludePackage("java");
excludePackage("com.sun");
excludePackage("sun");
excludePackage("jdk");
}
public boolean isClassLoaded(String name) {
return findLoadedClass(name) != null;
}
public byte[] getClassBytes(String name) throws IOException {
String binName = name.replace('.', '/');
String path = binName.concat(".class");
try (InputStream in = getResourceAsStream(path)) {
if (in == null)
return null;
return in.readAllBytes();
}
}
public void excludePackage(String name) {
exclusions.add(name + '.');
}
@Override
public void addURL(URL url) {
super.addURL(url);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
for (String prefix : exclusions) {
if (name.startsWith(prefix)) {
return SYSTEM.loadClass(name);
}
}
Class<?> loaded = findLoadedClass(name);
if (loaded != null)
return loaded;
Class<?> result = findClass(name);
if (resolve)
resolveClass(result);
return result;
}
}
@Override
public synchronized Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] bytes = getClassBytes(name);
if (bytes == null)
throw new ClassNotFoundException(name);
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
@Nullable
@Override
public URL getResource(String name) {
URL parentUrl = super.getResource(name);
if (parentUrl != null)
return parentUrl;
return SYSTEM.getResource(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
Enumeration<URL> parentResources = super.getResources(name);
Enumeration<URL> systemResources = SYSTEM.getResources(name);
if (parentResources.hasMoreElements() && systemResources.hasMoreElements()) {
List<URL> list = new ArrayList<>();
while (parentResources.hasMoreElements())
list.add(parentResources.nextElement());
while (systemResources.hasMoreElements())
list.add(systemResources.nextElement());
return Collections.enumeration(list);
}
if (parentResources.hasMoreElements())
return parentResources;
if (systemResources.hasMoreElements())
return systemResources;
return Collections.enumeration(Collections.emptyList());
}
}

View file

@ -1,50 +0,0 @@
package org.ecorous.esnesnon.nonsense.loader.impl.launch;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
public class MixinClassloader extends URLClassLoader {
static {
registerAsParallelCapable();
}
public MixinClassloader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@Override
public void addURL(URL url) {
super.addURL(url);
}
public boolean isClassLoaded(String name){
return findLoadedClass(name) != null;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] bytes = getClassBytes(name);
if (bytes == null) {
throw new ClassNotFoundException(name);
}
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException aa) {
throw new ClassNotFoundException(name, aa);
}
}
public byte[] getClassBytes(String name) throws IOException {
String binName = name.replace(".", "/");
String path = binName.concat(".class");
try (InputStream in = getResourceAsStream(path)) {
if (in == null)
return null;
return in.readAllBytes();
}
}
}