how is the control flow to findClass of
Asked Answered
F

2

6

In the parent delegation model for loading classes, I know that loadclass() is invoked on the parent, all the way to the top of the class-loader hierarchy (assuming the class is not loaded). At which point the topmost parent classloader's findClass is invoked. If this class is not found, how is the control transferred to the next classloader's findClass method ?

Fowlkes answered 23/8, 2010 at 3:39 Comment(0)
S
20

The findClass(String) will be invoked by the loadClass(String) method of the classloader. It's default implementation throws a ClassNotFoundException and is intended to be overridden by classloaders.

The loadClass(String) method will call the following methods in that order

  • First it tries to find if the class already loaded: findLoadedClass(String)
  • Then if not found it calls the parent' classloaders loadClass(String) method.
  • If not found, it will call the findClass(String) method (custom loading)

So all a custom classloader has to do is override the findClass(String) method to load classes in a custom way. This will ensure the proper delegation in classloading. Check the links (javadoc), it explains what steps are taken and how the findClass(String) is called from loadClass(String)

So the classloading takes place in following order (example) ClassLoader A with parent B (only explaining the findClass and loadClass)

               A.loadClass()
                    |
                (not-found?) (by findLoadedClass)
                    |
               B.loadClass()
                    |
                (not found?) (by findLoadedClass)
                    |
         systemclassloader.loadClass()  (Bs parent, also can be 
                    |                    called classpath classloader)
                    |
                (not found?) (by findLoadedClass)
                    |
        bootstrap classloader.loadClass() (the bootstrap classloader, 
                    |                      this has no parent)
                    |
                (not found?)
                    |
         systemclassloader.findClass()  (on system classloader, 
                    |                    will try to "find" class in "classpath")
                    |
                (not found?)
                    |
                B.findClass()
                    |
                (not found?)
                    |
                A.findClass()
                    |
                 (not found?)
                    |
            ClassNotFoundException

At any given time if the class is found (eigther by findClass or findLoadedClass), that class is returned.

Seigniory answered 23/8, 2010 at 4:10 Comment(5)
nice. I guess I was not thinking clearly- you illustrate it very well. The thing that is not very explicit in your diagram but is perhaps implied and the missing puzzle piece for me is that every-time control returns from a loadClass of an ancestor classloader with null, the previous classloader calls findClass method. Is it required that every findClass method return a valid class or throw a ClassNotFoundException ?Fowlkes
Thanks, yes, its required that it either returns the class or throws a ClassNotFoundException, or else you will get a NullPointerExceptionSeigniory
On a related note- do you know where the restriction that a class once loaded by a class-loader cannot be reloaded comes from ? I did not see any mention of it in the spec...what prevents a classloader from over-riding loadClass and not check findLoadedClass before proceeding to load another version ?Fowlkes
There's no restriction on this, if there was there'd be no features like hot deployment, etc. Its just documented that normally these rules should be followed, but it is not a rule. Your app may need clasess to be loaded in a different order altogether. Thats the magic of it! Thats why we have frameworks like osgi, webapps, and cool things like hot deployment :)Seigniory
Given the same class, will A_classloader get a different result with B_classloader by calling findLoadedClass?Alberthaalberti
D
4

The above explanation is comprehensive and excellent. A more straightforward way to understand the principle of delegation class loading to is read the source code. Any way, the source code is not complex at all.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/ClassLoader.java#400

400     protected Class<?> loadClass(String name, boolean resolve)
401         throws ClassNotFoundException
402     {
403         synchronized (getClassLoadingLock(name)) {
404             // First, check if the class has already been loaded
405             Class c = findLoadedClass(name);
406             if (c == null) {
407                 long t0 = System.nanoTime();
408                 try {
409                     if (parent != null) {
410                         c = parent.loadClass(name, false);
411                     } else {
412                         c = findBootstrapClassOrNull(name);
413                     }
414                 } catch (ClassNotFoundException e) {
415                     // ClassNotFoundException thrown if class not found
416                     // from the non-null parent class loader
417                 }
418 
419                 if (c == null) {
420                     // If still not found, then invoke findClass in order
421                     // to find the class.
422                     long t1 = System.nanoTime();
423                     c = findClass(name);
424 
425                     // this is the defining class loader; record the stats
426                     sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
427                     sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
428                     sun.misc.PerfCounter.getFindClasses().increment();
429                 }
430             }
431             if (resolve) {
432                 resolveClass(c);
433             }
434             return c;
435         }
436     }
Doubleedged answered 8/11, 2012 at 6:9 Comment(1)
just wanna add a comment here, notice how synchronized block is on the class name, this is an enhancement in java 7, before that in java 6 the whole method was synchronizedHilltop

© 2022 - 2024 — McMap. All rights reserved.