Child-first mod class loading

This commit is contained in:
Anuken
2021-06-09 10:04:23 -04:00
parent a8a163ebe2
commit adf6465029
3 changed files with 59 additions and 21 deletions
@@ -75,7 +75,27 @@ public class AndroidLauncher extends AndroidApplication{
@Override @Override
public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{ public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent); return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//check for loaded state
Class<?> loadedClass = findLoadedClass(name);
if(loadedClass == null){
try{
//try to load own class first
loadedClass = findClass(name);
}catch(ClassNotFoundException e){
//use parent if not found
loadedClass = super.loadClass(name, resolve);
}
}
if(resolve){
resolveClass(loadedClass);
}
return loadedClass;
}
};
} }
@Override @Override
+22 -2
View File
@@ -21,9 +21,29 @@ import static mindustry.Vars.*;
public interface Platform{ public interface Platform{
/** Dynamically creates a class loader for a jar file. */ /** Dynamically creates a class loader for a jar file. This loader must be child-first. */
default ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{ default ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
return new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, parent); return new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, parent){
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//check for loaded state
Class<?> loadedClass = findLoadedClass(name);
if(loadedClass == null){
try{
//try to load own class first
loadedClass = findClass(name);
}catch(ClassNotFoundException e){
//use parent if not found
loadedClass = super.loadClass(name, resolve);
}
}
if(resolve){
resolveClass(loadedClass);
}
return loadedClass;
}
};
} }
/** Steam: Update lobby visibility.*/ /** Steam: Update lobby visibility.*/
+7 -9
View File
@@ -11,13 +11,11 @@ public class ModClassLoader extends ClassLoader{
} }
@Override @Override
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ protected Class<?> findClass(String name) throws ClassNotFoundException{
//always try the superclass first
try{
return super.loadClass(name, resolve);
}catch(ClassNotFoundException error){
//a child may try to delegate class loading to its parent, which is *this class loader* - do not let that happen //a child may try to delegate class loading to its parent, which is *this class loader* - do not let that happen
if(inChild) throw error; if(inChild) throw new ClassNotFoundException(name);
ClassNotFoundException last = null;
int size = children.size; int size = children.size;
//if it doesn't exist in the main class loader, try all the children //if it doesn't exist in the main class loader, try all the children
for(int i = 0; i < size; i++){ for(int i = 0; i < size; i++){
@@ -26,10 +24,10 @@ public class ModClassLoader extends ClassLoader{
var out = children.get(i).loadClass(name); var out = children.get(i).loadClass(name);
inChild = false; inChild = false;
return out; return out;
}catch(ClassNotFoundException ignored){ }catch(ClassNotFoundException e){
last = e;
} }
} }
throw error; throw (last == null ? new ClassNotFoundException(name) : last);
}
} }
} }