Child-first mod class loading
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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.*/
|
||||||
|
|||||||
@@ -11,25 +11,23 @@ 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
|
//a child may try to delegate class loading to its parent, which is *this class loader* - do not let that happen
|
||||||
try{
|
if(inChild) throw new ClassNotFoundException(name);
|
||||||
return super.loadClass(name, resolve);
|
|
||||||
}catch(ClassNotFoundException error){
|
ClassNotFoundException last = null;
|
||||||
//a child may try to delegate class loading to its parent, which is *this class loader* - do not let that happen
|
int size = children.size;
|
||||||
if(inChild) throw error;
|
//if it doesn't exist in the main class loader, try all the children
|
||||||
int size = children.size;
|
for(int i = 0; i < size; i++){
|
||||||
//if it doesn't exist in the main class loader, try all the children
|
try{
|
||||||
for(int i = 0; i < size; i++){
|
inChild = true;
|
||||||
try{
|
var out = children.get(i).loadClass(name);
|
||||||
inChild = true;
|
inChild = false;
|
||||||
var out = children.get(i).loadClass(name);
|
return out;
|
||||||
inChild = false;
|
}catch(ClassNotFoundException e){
|
||||||
return out;
|
last = e;
|
||||||
}catch(ClassNotFoundException ignored){
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
throw (last == null ? new ClassNotFoundException(name) : last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user