I have read somewhere that if class A is loaded by ClassLoaderA then all the classes A depends on will be loaded by ClassLoaderA. Is it true? If it is true, then why we need to set the context class loader? like this one: http://blog.markturansky.com/archives/21, thanks in advance.
2 Answers
The Javadocs say the following about the class loaders:
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
As such, the statement in your question is apparently wrong.
There are cases in which you might like to create an isolated class loader, that is, a class loader not tied to the application class loader chain. In those cases you could create a class loader whose parent is null. (i.e. check constructors in URLClassLoader class)
This means that if this isolated class loader cannot find/load a given class it will immediately fail with a ClassNotFoundException. This means also that you can have two independent hierarchies of class loaders not interfering with each other.
-EDIT-
I am going to illustrate my answer. Assume that:
- I have an interface called
Creaturelocated in a JAR file calledparent.jar. - I have an class called
Jedilocated in a JAR file calledchild.jar. - The class
Jediimplements the interfaceCreature.
Now, let's create a chain of class loaders, independent of the current system chain.
ClassLoader parent = new URLClassLoader(new URL[]{parentJar.toURL()}, null);
ClassLoader child = new URLClassLoader(new URL[]{childJar.toURL()}, parent);
Now, we can ask the child class loader to load the class Jedi.
Class<?> klass1 = child.loadClass("com.star.wars.Jedi");
Now, if you query its class loader, you will see that it was loaded by the child class loader. So far so good. But what about the interface it implements. It depends on it, but the Creature interface was only available to its parent class loader, right?
Well, if you request the klass1.getInterfaces()[0].getClassLoader() you will notice that it is the parent class loader.
This proves that the statement:
if class A is loaded by ClassLoader A then all the classes A depends on will be loaded by ClassLoader A.
is totally false.
3 Comments
mainClass is already loaded by the URLClassLoader, then all the classes it depends on will be loaded by the same loader(or the loader' parent loader), why we need to call Thread.currentThread().setContextClassLoader(classloader);?What you read is correct. By default, all classes just reference each other and end up with the same ClassLoader. The link you provide explains how to do the opposite. Multiple classes loaded in the same JVM can have the same name (including package name) but different definitions. Generally, this happens when they are from different versions of the same library. How can you make sure that the code using library version 1 always sees version 1 and the code using library version 2 always sees version 2? You do this with ClassLoader isolation through a bootstrap ClassLoader as described at the link you provided.
2 Comments
mainClass is already loaded by the URLClassLoader, then all the classes it depends on will be loaded by the same loader(or the loader' parent loader), why we need to call Thread.currentThread().setContextClassLoader(classloader);?