When calling loadClass()
on a ClassLoader, does the ClassLoader
first check if the class has been loaded, or does it immediately delegate this check to
The two statements are not exactly mutually exclusive. The Class will only exist in the current ClassLoader's set of loaded classes if the parent ClassLoader had previously failed to find the Class. So,
When requested to find (the external data that describes) a class or resource, a ClassLoader instance will delegate the search for (the external data that describes) the class or resource to its parent class loader before attempting to find (the external data that describes) the class or resource itself.
Which does not prevent it from short-circuiting if it knows its parent can't find the class but it can (as shown by it previously loading the class)
There's one more issue that should be noted in this context. The API doc says:
The methods and constructors of objects created by a class loader may reference other classes. To determine the class(es) referred to, the Java virtual machine invokes the loadClass method of the class loader that originally created the class.
Meaning that networks of referencing classes are loaded by the same class loader.
This is basically how it works. You type
Foo f = new Foo();
At this point the classloader will determine if Foo()
have been loaded viz its bits in memory/perm gen. If it has been loaded, then use that. Otherwise delegate it to the parent class loader to try to resolve the class. The bits of this class are read from disk then loaded into memory. On the next new Foo()
, the class would now be found in memory/loaded.
The Java API is correct.
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.
From the Java Classloading Mechanism -
When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.
To concur with Sri's answer, it will always get delegated to the parent and the api is correct. If you are playing with classloading, this can make things a little tricky to get right, or achieve the effects you are after. I would suggest starting the jvm with a minimal classpath and then loading all classes using your custom classloader, the easiest way to do this is to use a URLClassloader or a composite object wrapping a URLClassloader so you would be able to trace which classes are loaded and when.
Also worth bearing in mind that a class A loaded by classloader C != class A loaded by classloader C if C and D are not part of the same classloader-parent-child hierarchy.
A proper class loader implementation will:
The default implementation of ClassLoader.loadClass is something like:
protected synchronized Class<?> loadClass(String name, boolean resolve) {
// First, check if this class loader has directly defined the class or if the
// JVM has initiated the class load with this class loader.
Class<?> result = findLoadedClass(name);
if (result == null) {
try {
// Next, delegate to the parent.
result = getParent().loadClass(name);
} catch (ClassNotFoundException ex) {
// Finally, search locally if the parent could not find the class.
result = findClass(ex);
}
}
// As a remnant of J2SE 1.0.2, link the class if a subclass of the class
// loader class requested it (the JVM never calls the method,
// loadClass(String) passes false, and the protected access modifier prevents
// callers from passing true).
if (resolve) {
resolveClass(result);
}
return result;
}
Some class loader implementations will delegation to other non-parent class loaders (OSGi, for example, delegates to a graph of class loaders depending on the package), and some class loader implementations will look for classes in a local classpath before delegating.