First off, I know this question has been asked before, but none of the solutions i have seen worked for me!
In order to be able to override existing implementations of classes with new bytecode I want a class loader(set as default) where all calls for any class(excluding java packages like "java.") go through my loadClass/findClass overridden methods. From there i can check a static registry to see if there is a override for that class. I am willing to try to do this differently, but so far this looks like the fastest and easiest solution.
My issue is that for some reason even when I set my loader as the default in VM args(-Djava.system.class.loader=my.package.path.ProxyClassLoader
) It throws the loading(of a class) to the parent which then, I assume sets the classloader to itself. This means all calls to find or load classes now go through the parent instead of my classloader.
Additionally, i would like to use JUnit to test this, but i couldnt get it to use a custom classloader(Using the JUnit API with the JUnit Engine in gradle) so i just went old school and used a main(where i can modifier vm arguments).
Things i have tried:
Here is my classloader as is:
public class ProxyClassLoader extends ClassLoader {
public ProxyClassLoader(ClassLoader parent) {
super(parent);
Thread.currentThread().setContextClassLoader(this);
}
//Didn't look like i need to override anything so
//this is just a simplicity thing for me(i call it through other classes)
public Class<?> defineClass(byte[] b, String name) {
return super.defineClass(name, b, 0, b.length, defaultDomain);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (ClassManager.hasOverload(name)) return ClassManager.retrieve(name);
return super.loadClass(name, resolve);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return this.loadClass(name, true);
}
}
Thanks!
Don't skip super class loaders completely. Try something like this?
@Override protected Class<?> loadClass(String name, boolean resolve) throws
ClassNotFoundException {
if(name belongs to java classes) {
return super.loadClass(name, resolve);
}
byte[] b = ..// read bytes from your .class files. or use getResourceAsStream(name)
Class<?> c = defineClass(b, name);
if(resolve) resolveClass(c);
return c;
}