Do you really get class loaders?<br />Jevgeni KabanovFounder & CTO of ZeroTurnaround<br />
My Background<br />Creator and core developer of JRebel<br />JRebelmaps your project workspace directly to a running appli...
To create JRebel we…<br />Hooked into class loading on the JVM level<br />Integrated with the class loading mechanism in m...
Overview<br />Basics<br />What is class loading?<br />How was it meant to work?<br />Problems and solutions<br />How do cl...
Basics<br />
Class loader API<br />publicabstractclassClassLoader {<br />  public Class loadClass(String name);<br />  protected Class ...
Class loading<br />publicclass A {<br />publicvoiddoSmth() {<br />    B b = new B();<br />b.doSmthElse();<br />  }<br />}<...
Delegation<br />Class loaders have a parent class loader<br />The parent is usually consulted first<br />Avoids loading sa...
Java EE Delegation<br />
Problems and solutions<br />
No class found<br />Variants<br />ClassNotFoundException<br />ClassNoDefFoundException<br />Helpful<br />IDE class lookup ...
Wrong class found<br />Variants<br />IncompatibleClassChangeError<br />AbstractMethodError<br />NoSuch(Method|Field)FoundE...
More than one class found<br />Variants<br />LinkageError (class loading constraints violated)<br />ClassCastException, Il...
More than one class found<br />Shared ClassLoader<br />ClassCastException<br />Util3<br />Factory3<br />Factory3.instanceU...
More than one class found<br />Shared ClassLoader<br />LinkageError<br />Util3<br />Factory3<br />Factory3.instance();<br ...
More than one class found<br />Shared ClassLoader<br />IllegalAccessError<br />Util3<br />Factory3<br />Factory3.instanceP...
Reloading an Object<br />OldClassLoader<br />NewClassLoader<br />MyObject.class<br />MyObject.class<br />Recreate the obje...
Leaking ClassLoaders<br />ClassLoader<br />Class1.class<br />Class2.class<br />Class3.class<br />Static Fields<br />Static...
Leaking ClassLoaders<br />Example.class<br />Example.class<br />Example.class<br />ExampleFactory$1<br />ExampleFactory$1<...
State of the art<br />
Hierarchy is not enough?<br />Isolation <br />Different versions of the same library<br />Performance<br />Class lookup is...
The Modern Way<br />Each JAR has own class loader<br />All class loaders are siblings, with one central repository<br />Ea...
Modern Filtering<br />classMClassLoaderextendsClassLoader {<br />// Initialized during startup from imports<br />  Set<Str...
Modern Lookup<br />classMRepository {<br />  // Initialized during startup from exports<br />  Map<String,List<MClassLoade...
Troubleshooting<br />The same tricks also work with Modern class loading systems<br />ClassLoader.getResource();<br />-ver...
Problems<br />Too restrictive<br />Import is a one-way street<br />If you want to use Hibernate, you import it, but it can...
Conclusions<br />The trick of troubleshooting class loaders is understanding how they work :)<br />Modern systems add a le...
Upcoming SlideShare
Loading in …5
×

Do you really get class loaders?

7,367 views

Published on

Published in: Technology
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,367
On SlideShare
0
From Embeds
0
Number of Embeds
18
Actions
Shares
0
Downloads
165
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide
  • Class loaders are Java objectsClass loaders are responsible forFinding resourcesResolving class names into Class objectsOriginally motivated by applets
  • Every class has a reference to its class loader objectMyClass.class.getClassLoader()
  • Do you really get class loaders?

    1. 1. Do you really get class loaders?<br />Jevgeni KabanovFounder & CTO of ZeroTurnaround<br />
    2. 2. My Background<br />Creator and core developer of JRebel<br />JRebelmaps your project workspace directly to a running application, watches the changes you make to classes and resources, then intelligently reflects them in your application.<br />With JRebel you can get an extra dev month a year by skipping builds & redeploys<br />30 day trial, just $149 per developer :)<br />
    3. 3. To create JRebel we…<br />Hooked into class loading on the JVM level<br />Integrated with the class loading mechanism in more than 10 different servers<br />Solved hundreds of issues connected to class loading<br />Learned a lot more about class loaders than we wanted to <br />
    4. 4. Overview<br />Basics<br />What is class loading?<br />How was it meant to work?<br />Problems and solutions<br />How do class loaders leak?<br />OSGi, Spring dm, JBoss and others<br />Conclusions <br />
    5. 5. Basics<br />
    6. 6. Class loader API<br />publicabstractclassClassLoader {<br /> public Class loadClass(String name);<br /> protected Class defineClass(byte[] b);<br /> public URL getResource(String name);<br /> public Enumeration getResources(String name);<br /> publicClassLoadergetParent()<br />}<br />
    7. 7. Class loading<br />publicclass A {<br />publicvoiddoSmth() {<br /> B b = new B();<br />b.doSmthElse();<br /> }<br />}<br />Causes a call to<br />A.class.getClassLoader().loadClass(“B”);<br />
    8. 8. Delegation<br />Class loaders have a parent class loader<br />The parent is usually consulted first<br />Avoids loading same class several times<br />However in a Java EE web module local classes are searched first<br />In Java EE each WAR module of an EAR gets its own class loader<br />This allows separate namespaces for applications in same container<br />
    9. 9. Java EE Delegation<br />
    10. 10. Problems and solutions<br />
    11. 11. No class found<br />Variants<br />ClassNotFoundException<br />ClassNoDefFoundException<br />Helpful<br />IDE class lookup (Ctrl+Shift+T in Eclipse)<br />find *.jar -exec jar -tf '{}' ; | grepMyClass<br />URLClassLoader.getUrls()<br />Container specific logs <br />
    12. 12. Wrong class found<br />Variants<br />IncompatibleClassChangeError<br />AbstractMethodError<br />NoSuch(Method|Field)FoundError<br />ClassCastException, IllegalAccessError<br />Helpful<br />-verbose:class<br />ClassLoader.getResource()<br />javap -private MyClass<br />
    13. 13. More than one class found<br />Variants<br />LinkageError (class loading constraints violated)<br />ClassCastException, IllegalAccessError<br />Helpful<br />-verbose:class<br />ClassLoader.getResource()<br />
    14. 14. More than one class found<br />Shared ClassLoader<br />ClassCastException<br />Util3<br />Factory3<br />Factory3.instanceUntyped();<br />new Util3()<br />Util3<br />Test3<br />Web ClassLoader<br />Util3 u = (Util3) Factory3.instanceUntyped();<br />
    15. 15. More than one class found<br />Shared ClassLoader<br />LinkageError<br />Util3<br />Factory3<br />Factory3.instance();<br />new Util3()<br />Util3<br />Test4<br />Web ClassLoader<br />Factory3.instance().sayHello();<br />
    16. 16. More than one class found<br />Shared ClassLoader<br />IllegalAccessError<br />Util3<br />Factory3<br />Factory3.instancePackage();<br />new Util3()<br />Util3<br />Test5<br />Web ClassLoader<br />Util3 u = (Util3) Factory3.instancePackage();<br />
    17. 17. Reloading an Object<br />OldClassLoader<br />NewClassLoader<br />MyObject.class<br />MyObject.class<br />Recreate the object<br />MyObject<br />MyObject<br />
    18. 18. Leaking ClassLoaders<br />ClassLoader<br />Class1.class<br />Class2.class<br />Class3.class<br />Static Fields<br />Static Fields<br />Static Fields<br />
    19. 19. Leaking ClassLoaders<br />Example.class<br />Example.class<br />Example.class<br />ExampleFactory$1<br />ExampleFactory$1<br />ExampleFactory$1<br />Leak.class<br />Leak.class<br />Leak.class<br />Leak<br />Leak<br />Leak<br />
    20. 20. State of the art<br />
    21. 21. Hierarchy is not enough?<br />Isolation <br />Different versions of the same library<br />Performance<br />Class lookup is very slow<br />Restricted<br />Why siblings can’t see each other’s classes?<br />OSGi, JBoss, NetBeans and others implement a different system<br />
    22. 22. The Modern Way<br />Each JAR has own class loader<br />All class loaders are siblings, with one central repository<br />Each JAR explicitly declares<br />Packages it exports<br />Packages it imports<br />Repository can find relevant class loaders by package<br />
    23. 23. Modern Filtering<br />classMClassLoaderextendsClassLoader {<br />// Initialized during startup from imports<br /> Set<String> imps;<br />public Class loadClass(Stringname) {<br /> String pkg = name.substring(0, <br />name.lastIndexOf('.'));<br />if (!imps.contains(pkg))<br />returnnull;<br />returnrepository.loadClass(name);<br /> }<br />}<br />
    24. 24. Modern Lookup<br />classMRepository {<br /> // Initialized during startup from exports<br /> Map<String,List<MClassLoader>> exps;<br /> publicClass loadClass(String name) {<br /> String pkg = name.substring(0, <br />name.lastIndexOf('.'));<br /> for (MClassLoadercl : exps.get(pkg)) {<br /> Class result = cl.loadLocalClass(name);<br /> if (result != null) return result;<br /> }<br /> returnnull;<br /> }<br />}<br />
    25. 25. Troubleshooting<br />The same tricks also work with Modern class loading systems<br />ClassLoader.getResource();<br />-verbose:class<br />Often can be supplemented with custom tools<br />Need to think in terms of export/import in addition to classpath<br />Looking at the pseudocode can help<br />
    26. 26. Problems<br />Too restrictive<br />Import is a one-way street<br />If you want to use Hibernate, you import it, but it cannot access your classes<br />Easy to leak<br />Any references between class loaders are leaks waiting to happen <br />Deadlocks<br />JVM enforces a global lock on loadClass() <br />
    27. 27. Conclusions<br />The trick of troubleshooting class loaders is understanding how they work :)<br />Modern systems add a level of complexity on top of an abstraction that nobody gets to begin with<br />When redeploying or reloading classes leaking is easy and leads to OOM<br />We need better tools to troubleshoot class loaders!<br />

    ×