understanding classloaders
TRANSCRIPT
Understanding classloaders
What will you learn
● How classloaders work● reasons, Class and Classloader basics, semantics, Java SE/EE
delegation mechanism, ClassLoader API
● Modern classloaders● Implementation of simple classloader● Pitfalls
Reasons for ClassLoaders
● when you need to load classes from different places that just classpath
● applets● plugin systems
● when you need support for running the same library with multiple versions within the same JVM
● module systems
● necessary for implementing "hotswap" functionality● web containers & application servers
● JNI native libraries
java.lang.Class overview
● represents a type (class, interface, enum, annotation, primitive marker) in the JVM
● allocates memory in both heap and permanent generation
● is always referenced by every object instance of the class
● holds a reference to its ClassLoader● is able to load resources
java.lang.Class
● can be acquired● by class literal String.class● from object object.getClass();● through ClassLoader Class.forName(String name);
Class identity
● "every Class is uniquely identified by its fully qualified name"
● starting from Java 1.2 not true any more● because of security reasons
● JLS 4.3.4 (When reference types are the same)● both are class or interface types● both are defined by the same classloader● both have the same binary name
Class identity
● changes added higher complexity resulting in interesting new classloading options as well as new problems and pitfalls
ClassLoader overview
● instance of java.lang.ClassLoader● responsible for loading classes● knows how to transform raw data (bytes) into
instance of Class● holds a strong reference to all classes it loads● has an optional parent for delegating
ClassLoader references
● starting from Java 1.2, 4 types of references on JVM:● strong reference● soft reference● weak reference● phantom reference
ClassLoader lazy loading principle
public class Foo { public static void main(String[] args) { pack.Bar bar = new pack.Bar(); bar.coolMethod(); }}
ClassLoader lazy loading principle
public class Foo { public static void main(String[] args) { pack.Bar bar = new pack.Bar(); bar.coolMethod(); }}
ClassLoader lazy loading principle
public class Foo { public static void main(String[] args) { pack.Bar bar = new pack.Bar(); bar.coolMethod(); }}
semantically causes similar call to
Foo.class.getClassLoader().loadClass("pack.Bar");
ClassLoader delegation mechanism
● ClassLoader has a parent ClassLoader● parent ClassLoader should be consulted first
● "parent first delegation model"● the reason is to avoid loading the same class several times● every ClassLoader except OSGi and Web App ClassLoader
● exact delegation depends on ClassLoader implementation
Java SE delegation mechanism
Java SE delegation mechanism
Java SE delegation mechanism
Java SE delegation mechanism
Java EE delegation mechanism
● no Java EE specification provides a standard for class loading
● however, Java EE defines the visibility and sharing of classes between different modules
● Web Application ClassLoader is different from all others
● instead of first asking its parent, it will first look itself for the class and then ask the parent
● each WAR of an EAR gets its own ClassLoader● this allows separate namespaces for applications in the same
container
Java EE delegation mechanism
Java EE delegation mechanism
Java EE delegation mechanism
Java EE delegation mechanism
Java EE delegation mechanism
Java EE delegation mechanism
ClassLoader API
● public Class<?> loadClass(String name);
● protected Class<?> findClass(String name);
● protected final Class<?>
defineClass(String name, byte[] b, inf off, int len);
● public ClassLoader getParent();
● public URL getResource(String name);
● public InputStream getResourceAsStream(String name);
● public Enumeration<URL> getResources();
Showcase
● OpenJDK java.lang.ClassLoader source code examination
● flow of 3 dependent ClassLoaders
● simple ClassLoader implementation● ClassNotFoundException vs NoClassDefFoundError
Modern ClassLoaders
● because tree hierarchy is not enough● in terms of isolation, performance, restrictions
● modern way● each JAR has its own ClassLoader● ClassLoaders are siblings, with one central repository● each JAR explicitly decalres packages it exports and imports● repository can find relevant ClassLoaders by package● libraries packed into separate modules
● examples● OSGi, NetBeans module system, JBoss Modules
Showcase
● Multiparent ClassLoaders● solving multiple versions of the same library problem
Common problems
● too many various errors can be thrown● AbstractMethodError, IllegalAccessError,
IncompatibleClassChangeError, LinkageError, NoClassDefFoundError, NoSuchFieldError, NoSuchMethodError, OutOfMemoryError
● and exceptions too● ClassCastException, ClassNotFoundException
● possible deadlocks● most of them are caused by invalid synchronization of
classes between IDE and deployed packages
Common problems
● many of them can be tracked by using tools● URLClassLoader.getURLs();● ClassLoader.getResource(String);● javap tool● java -verbose:class
Common pitfalls + code samples
● ClassCastException● because of Java 1.2 changes in ClassLoader architecture
● OutOfMemoryError (both Heap and Permgen)● often during HotDeploy● because ClassLoaders are leaking● because there are too many different classes
● Singletons (and not only them)● because of static attributes
Interesting projects
● JRebel● Javaleon● HotSwap● Tattletale● OSGi● NetBeans module system● JBoss Modules● Project jigsaw