Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UrlClassLoader delegation and inheritance hierarchy

I have been confused with UrlClassLoader delegation hierarchy and inheritance hierarchy. I created class that extends UrlClassLoader and executed: childOfUrlClassLoader.getParent().getClass().getName() which gave me: sun.misc.Launcher$AppClassLoader. After this I pay a visit to mentioned above class (source)

249 static class AppClassLoader extends URLClassLoader {
        //...
308     protected synchronized Class<?> loadClass(String name, boolean resolve)
309         throws ClassNotFoundException
310     {
311         // First, check if the class has already been loaded
312         Class c = findLoadedClass(name);
313         if (c == null) {
314             try {
315                 if (parent != null) {
316                     c = parent.loadClass(name, false);
317      
          // ...
329         return c;
330     }

Then I checked who is a parent of AppClassLoader. Expectedly I got sun.misc.Launcher$ExtClassLoader and the parent of ExtClassLoader is null.


I have a few questions:

1) Who loads my class since the code of AppClassLoader.loadClass has line

294    return (super.loadClass(name, resolve));

It looks like loop, doesn't it?

2) Why doesn't ExtClassLoader have BootstrapClassLoader as a parent, but has null?

3) For which purpose AppClassLoader class extends UrlClassLoader?

like image 448
Rudziankoŭ Avatar asked Dec 08 '15 16:12

Rudziankoŭ


1 Answers

Delegate-first model

The build-in java ClassLoaders follow a delegate-first model. This means that a ClassLoader will allow its parent to load a class before it tries to load it itself. The hierarchy of loaders has the bootstrap loader at the top, followed by the extension classloader, the application classloader. Under the application classloader can be found URLClassLoaders and any other loaders created by the application.

The bootstrap classloader can load files from rt.jar which contains the most essential java classes including those in the java.lang, java.io, java.util and java.net packages. The extension classloader loads classes from other jar files in the java installation. It is the application classloader which loads the classes found on the classpath and which is the current classloader when an application starts.

Loading in action

So what happens when an application wants to load a HashMap? The current classloader is asked to load the HashMap class. Before attempting anything, it asks its parent, the extension classloader to load the class. In turn the extension classloader delgates to the bootstrap classloader which finds the class in rt.jar and loads it.

If the class to be loaded is in the classpath, the request goes up to the bootstrap classloader as before to check rt.jar. The bootstrap loader fails to find the class, so the task is referred back to the extension classloader which searches the java installation for the class. When this fails the task reverts back to the application classloader which scans the classpath for the class.

The ClassLoader cache

In practice each classloader has a cache where classes already loaded are stored and the cache is searched before the delegation to the parent, but this does not alter the principle of delegating first.

This is where the cache is checked

Class c = findLoadedClass(name);

URLClassLoaders

A URLClassLoader created by an application will have the application ClassLoader as a parent. If it follows the delegate-first model, classes will be found in the classpath before the supplied URL.

The Questions

1) Who loads my class

I see slightly different code in your link

309         // First, check if the class has already been loaded
310         Class c = findLoadedClass(name);
311         if (c == null) {
312             try {
313                 if (parent != null) {
314                     c = parent.loadClass(name, false);
315                 } else {
316                     c = findBootstrapClass0(name);
317                 }
318             } catch (ClassNotFoundException e) {
319                 // If still not found, then invoke findClass in order
320                 // to find the class.
321                 c = findClass(name);
322             }
323         }

If a class is not loaded by the parent, it throws a ClassNotFoundException which is caught and allows the current ClassLoader to find the class

321                 c = findClass(name);

2) Why doesn't ExtClassLoader have BootstrapClassLoader as a parent, but has null?

This is answered by the getClassLoader API

[getClassLoader()] returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader.

3) For which purpose AppClassLoader class extends UrlClassLoader?

Consider that the application classloader is not special in that it loads classes supplied by the user, not system classes. The classpath is effectively a list of URIs so a URLClassLoader is a suitable superclass.

References

There are many article on classloading including

  • Internals on Java ClassLoading
  • Oracle Tutorial
like image 74
Neil Masson Avatar answered Oct 13 '22 15:10

Neil Masson