Understanding Java Class Loader

Understanding Java Class Loader

Typically class loaders are arranged in a parent/child hierarchy.
When a class loading request is presented to a class loader, it first asks its parent class loader to fulfill the request.
The parent, in turn, asks its parent for the class until the request reaches the top of the hierarchy.
If the class loader at the top of the hierarchy cannot fulfill the request, then the child class loader that called it is responsible for loading the class.
If it can't load the class, a ClassNotFoundException is thrown by the class loader.
Delegation Model
Class loaders are arranged hierarchically in a tree, with the bootstrap class loader as the root of the tree.
A loaded class in a JVM is identified by its fully qualified name and its defining class loader, so class A defined by class loader X is not same class as class A defined by class loader B. In Eclipse, each plugin has its class loader.
Java default class loaders
Bootstrap class loader
Bootstrap classloader is the parent of all classloaders and loads the standard JDK classes in lib directory of JRE (rt.jar and i18n.jar). All the java.* classes are loaded by this classloader.
Extensions class loader (ExtClassLoader)
Extensions Classloader is the immediate child of Bootstrap classloader. This classloader loads the classes in lib\ext directory of the JRE.
System class loader (AppClassLoader)
It loads the classes and jars specified by the CLASSPATH environment variable, java.class.path system property, -cp or –classpath command line settings. If any of the jars specified in one of the above manner have a MANIFEST.MF file with a Class-Path attribute, the jars specified by the Class-Path attribute are also loaded.

Bootstrap class loader is pretty special, in that it is implemented in native code. All other class loaders are written in Java (apart from some native methods) and extend the java.lang.ClassLoader class.
A class is identified uniquely in the context of the associated classloader.
Two objects loaded by different classloaders are never equal.
Three principles of Classloader operation
Delegation Principle
If a class is not loaded already, the classloaders delegate the request to load that class to their parent classloaders. This delegation continues until the top of the hierarchy is reached and the primordial classloader tries to load the class.
Visibility Principle
Classes loaded by parent classloaders are visible to child classloaders but not vice versa, sibling classloaders cannot see each other’s classes. Requests can only go to a parent class loader; they cannot go to a child class loader.
Uniqueness Principle
When a classloader loads a class, the child classloaders in the hierarchy will never reload that class.
In most implementations getClassLoader() method returns null for the bootstrap class loader.
J2EE classloader hierarchy and its implications
In J2EE, each application is packaged as an Enterprise ARchive (EAR). The EAR is a self-contained deployment unit having minimal dependencies on external classes (with the exception of application server classes).
An EAR file is composed of any number of following components: EJB-JAR, WAR, RAR, Dependency JAR, application.xml.
J2EE classloader hierarchy
When the parent classloader is below the System-Classpath Classloader in hierarchy, the child classloader can "see" the class only when it is specified in the manifest file for the child classloader. For instance, if an EJB application wants to reference util-a.jar and util-b.jar, then we can add the following entry into the EJB-JAR’s manifest file, MANIFEST.MF: Class-Path: util-a.jar util-b.jar
Every J2EE EAR gets its own classloader. This is the starting point for isolating application classes from one another. This classloader loads all the dependency libraries in the EAR, both EJB and the web module can see the class loaded by the EAR classloader.
An interesting question arises. Aren’t EJBs packaged as jars? How does the application server know to load the EJBs in a separate classloader? The simple answer is that it doesn’t, unless you tell it so. You have to explicitly specify which of the jars are EJB modules in application.xml – the deployment descriptor for the EAR.
WAR classloaders are the children of EJB classloader. The key difference between these classloaders is that while all EJB modules whether in the single or different EJB-JARs, share the same EJB classloader, each WAR gets its own classloader. All of the WAR classloaders however inherit from the same parent - EJB classloader. The rationale behind this hierarchy is that EJBs contain the core of the business logic and web applications have to "see" them to invoke their business methods. Of course to "see" them the WAR manifest file has to have an entry as shown earlier.
WebLogic class loader

One EJB class loader is created as a child of the system class loaders. It is responsible for loading all EJB .jar classes for all EJB .jar files in the .ear.
One web application class loader is created for each .war in the .ear, and each of the web application class loaders is a child of the EJB class loader. The web application class loaders are responsible for loading the classes and jars in the WEB-INF/classes and WEB-INF/lib directories in the corresponding .war.   
.jar files listed in a Manifest Class-Path entry are loaded by the application's EJB class loader. This applies to Manifest Class-Path entries found in EJB .jar files and web application .war files within the .ear.
One advantage of this class loading architecture is the automatic availability of all EJB classes from the web application class loaders. However, classes found in the WEB-INF/classes or WEB-INF/lib directories of a .war are not available to any EJB classes.
A WebSphere extensions class loader
The WebSphere extensions class loader loads the WebSphere Application Server classes that are required at run time. The extensions class loader uses a ws.ext.dirs system property to determine the path that is used to load classes. Each directory in the ws.ext.dirs class path and every Java archive (JAR) file or ZIP file in these directories is added to the class path used by this class loader.
One or more application module class loaders that load elements of enterprise applications running in the server
The application elements can be Web modules, enterprise bean (EJB) modules, resource adapter archives (RAR files), and dependency JAR files. Application class loaders follow Java EE class-loading rules to load classes and JAR files from an enterprise application. The product enables you to associate shared libraries with an application.
Zero or more Web module class loaders
By default, Web module class loaders load the contents of the WEB-INF/classes and WEB-INF/lib directories. Web module class loaders are children of application class loaders. You can specify that an application class loader load the contents of a Web module rather than the Web module class loader.
Java class loader
This kind of tree like class loader supports delegation, visibility and uniqueness principle inherently.
Conflicting classes
You have a program, running on JRE 1.6, it needs latest and greatest xerces 2.9 explicitly. You have bundled the xerces jar with your program, and its included in the classpath. But during runtime, older version of xerces classes are getting loaded irrespective of your settings. You guessed it right! Its because JRE 1.6 ships xerces and it is already loaded by extension class loader. This is the primary problem of hierarchical class loader, at runtime all jars become a long list of files which is searched in a sequential order in the order of their loading.
Explicit dependencies can not be defined
Let’s say your program needs Apache commons-logging, xerces and a long list of popular open source components. When you ship your product, either you have to build the stack yourself and hand it over to the customer or communicate this through a user documentation. The so called logical unit of a java program, the jar, lacks the place holder in its meta-data to include information about its dependency.
Version dependency problem
Problem gets complicated when you explicitly need commons-logging 1.1.1, xerces 2.9 and so on, and your program is supposed to be part of a larger system which already has these libraries and their versions are not same as yours. You will have sleep less night in recompiling your program with those libraries to co-exist. Phew !! I have been through this many times.
Entire jar is exposed
When you are building java libraries you want the user to use only few classes which are meant be used. But today Java doesn't have any mechanism to define access specifiers at a class level. Once the jar is in the classpath all core classes can be seen and instantiated.
J2EE class loader
Class loader remains hierarchical but with support for isolation across multiple applications in the same container.
Application A, lets say an ear, has its own class loader and has loaded war and sar inside it. Another Application B, another ear, has its own class loader and can not see Application A's classes. Now if you have a need to share classes between these two applications, either you have to make them use the same class loader or push the shared classes up in the hierarchy to system class loader. By doing this the entire container will be able to see those shared classes even though other applications doesn't necessarily need them. JBoss has introduced unified class loader to address the same problem. But you have to be a pro to use that! Usually this is solved by duplicating jars.
OSGi class loader
Class loader in OSGi is a graph, unlike a hierarchical tree structure of Java and J2EE. Each bundle has its own class loader. For example bundle B defines an export list and bundle A imports it. When A requests a class to be loaded which is present in B, immediately call will be delegated to the class loader of B. As there is no long list of classes organized in a hierarchical structure anymore, it proves to be very fast and efficient. The process of resolving dependency based on import and export metadata is called resolution process. Its a complex procedure taken care by the OSGi framework.
Inherent advantage of having this kind of class loader is:
1. Export is defined with a version attribute, where as imports can specify a range of versions. This allows a bundle to say I need a library having a version between x and y.
2. All packages in a bundle need not stick to a version while exporting. Package org.gok can be exported under 0.9 and another package in the same bundle org.goh can be exported as 1.1.
3. Same library having different versions can be there in the application side by side
This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories.
It can be used to download classes from other directories or remote server.
Class loading is fundamental to two of the most compelling features of Java: dynamic linking and dynamic extension.
Dynamic linking allows types to be incrementally incorporated into a running JVM.
Dynamic extension allows the decision as to which types are loaded into a JVM to be deferred until runtime. This means that an application hosted by the JVM can leverage types that were previously unknown, or perhaps did not even exist, when the application was compiled.
Custom class loader
Usually, J2EE servers implement its custom class loader to enable features such as hot redeployment and application independence.
Normally, the class loaded by custom class loader is unknown to current class loader, we can't cast the object to real type, we can refer it as an object or refer it using its interface.
Basic steps to implement a custom class loader
We usually just need override loadClass() or findClass() method.
1.       Check whether the class has already been loaded, if already loaded, just return it.
2.       If not, check to see whether its parent class loader can load this class.
3.       If not, implement the logic to load it by its own.
4.       Define the class (call parent's method directly).
5.       Check whether the class has to be resolved (linked), and in that case, resolve it (call parent's method directly)..
6.       Return the Class object to the caller.

Post a Comment


Java (160) Lucene-Solr (112) Interview (64) All (58) J2SE (53) Algorithm (45) Soft Skills (39) Eclipse (33) Code Example (31) JavaScript (23) Linux (22) Spring (22) Windows (22) Tools (21) Web Development (20) Nutch2 (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) Troubleshooting (14) J2EE (13) Network (13) PowerShell (11) Problem Solving (10) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) UIMA (9) html (9) Http Client (8) Maven (8) Security (8) Tips (8) bat (8) blogger (8) Big Data (7) Database (7) Google (7) Guava (7) JSON (7) Shell (7) System Design (7) ANT (6) Coding Skills (6) Lesson Learned (6) Programmer Skills (6) Scala (6) css (6) Algorithm Series (5) Cache (5) Continuous Integration (5) IDE (5) adsense (5) xml (5) AIX (4) Become a Better You (4) Code Quality (4) Concurrency (4) Dynamic Languages (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Review (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Distributed (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Life (3) Python (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Fiddler (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Logging (2) Mac (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Firefox (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) Invest (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts