How do I change the default class loader in Java?
Suppose I have three classes, classA, example ClassB and example ClassLoader. ClassA prints out HelloWorld and ClassB imports example ClassA and call its main () method If I do this:
It works and uses my classloader But if I do this:
ClassB uses my classloader, but classA (imported by ClassB) uses the default classloader
Is there any way to force java to always use my classloader (unless another classloader is explicitly specified)?
Editor: thanks for the following ŭ According to loebermann's answer, I found that the problem is that I call the parent class loader to load the classes I don't need to touch, and those loaded classes are set as the context class loader, so the imported classes use the parent class loader of my custom loader (confusing, sorry) now I can read each class manually to make it work, but it looks a lot, because I copied the code of urlclassloader directly Is there any way to tell the parent class loader to find and define classes, but set the context class loader of class as your custom class loader?
Solution
If your class loader is implemented correctly, it will first ask its parent class loader for any classes that should be loaded
The parent class loader of your loader may be the usual application class loader This means that each class loaded by your class loader will be searched on the application class loader first and only if you can't find it
All classes defined by your classloader will also search for the required classes on the classloader If they do not, your classA is not loaded by your loader
If this doesn't help, you need to display some code about how to get the results
Ideas about what to do:
class ModifyingClassLoader extends urlclassloader { // TODO: add constructors private boolean needsModifying(String name) { // TODO } private byte[] modifyClass(InputStream original) throws IOException { // TODO } public Class<?> findClass(String name) throws { if(needsModifying(name)) { try { InputStream classData = getResourceAsStream(name.replace('.','/') + ".class"); if(classData == null) { throw new ClassNotFoundException("class " + name + " is not findable"); } byte[] array = modifyClass(classData); return defineClass(name,array,array.length); } catch(IOException io) { throw new ClassNotFoundException(io); } } else { return super.findClass(name); } } }
To your question:
No, the classloader of a class is always a class called to create the defineclass method of the class (context class loader is something else - it is thread specific and can only be used by classes that explicitly want to use it, rather than by resolving their own direct dependencies.)