Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login

You must be logged to download. Click here to login


MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation


MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Demystifying the Java ClassLoader

This article will present some important concepts regarding Java ClassLoader process, and they way the language deals with class loading.

Until recently, I did not give much importance in the functioning of the internal structure of the Java platform even when we have problems that Google does not know. To solve my problems I had to dig deep inside the JVM. Moreover, despite various materials on the network, it is difficult to understand the language and the inner workings of it. To begin to understand the operation of your program within the Java Virtual Machine (JVM) is necessary to understand the heart of the JVM ClassLoader (CL).

In an easy way, a CL is a structure that is responsible for the loading of the bytecode (.class). Each ClassLoader contains what it can carry in your specific classpath, that is, the address (directories) of our classes. A classpath can contain multiple directories, thus the CL will search for the class in the first directory specified, if it does not find the class it goes to the second, and then successively until finish the list of classpath directories. However, the most important is to understand how the CL load your classes and how it is organized internally.

First of all, it is necessary to explain that a type (class) in Java is identified by its name and its CL. For example, one object of Sheet class from CL 0x2bbd86 is different from an object of Sheet class from CL 0x813b2 because despite being the same class, they have different CLs. Java does this to ensure consistency of objects inside the JVM. Because, otherwise, it could cause a conflict between a Leaf object that represents a tree and its assignment to a leaf object that represents a payroll. I.e., objects originated from a class of the same name cannot have identical structures.

It is also important to understand the class loading key process, the delegation. One single ClassLoader has always a ClassLoader parent and will always do the following:

  • The class will always ask the ClassLoader that has loaded itself to load their dependencies;
  • ClassLoader will always delegate the loading of class to your father, to see if the same wants to load the class before.

Now, we will explain the hierarchy of ClassLoaders. When the JVM starts it has no loaded class. The JVM uses the class loading mechanism known as lazyness, and the JVM will be loading the classes as needed. But there is a problem, the code that loads a class is the ClassLoader that itself is a Java class, then if the JVM has no loaded class how it will load the other classes because according to the Java specification a class is loaded only when all its dependencies are loaded. As per the Java specification, ClassLoader inherits from Object which itself must be loaded by a ClassLoader which leads to a dead-lock. The solution to this is having a ClassLoader that, in fact, is not written in Java but in native code. This native CL will load the ClassLoader, AppClassLoader and ExtClassLoader classes. The hierarchy tree of a CL is formed by grouping some CLs. By default, we have the hierarchy defined in Figure 1.

Figure 1. Java Class loader hierarchy.

Bootstrap is the native CL run by the JVM and its classpath finds the system classes, mainly the runtime of Java. The ExtCL (Extension ClassLoader) has as its classpath user-specific frameworks or applications, if you want these to be visible across the VM. The father of ExtCL is Bootstrap. Finally, the AppClassLoader, which is the CL that will load your application and your classpath is specified in the manifest of the jar or passed on the command line, and the father of this is the ExtCL.

We will make an application to demonstrate these concepts. Let’s start by Listing 1.

Listing 1. Creating the Info class.

public class Info {  
   public static void main(String args[]) {  
      System.out.println("Boot class path: " + System.getProperty("sun.boot.class.path"));  
      System.out.println("Extension class path: " + System.getProperty("Java.ext.dirs"));  
      System.out.println("AppClassPath: " + System.getProperty("Java.class.path"));  
      Info i=new Info();  
      System.out.println("\nBoot CL: " + Java.lang.Object.class.getClassLoader());  
      System.out.println("App ClassLoader: " + i.getClass().getClassLoader());  

Results obtained in Listing 2.

Listing 2. Result of the execution.

$ Java Info  
Boot class path: /opt/Java/jre/lib/resources.jar:/opt/Java/jre/lib/rt.jar:/opt/Java/jre/lib/sunrsasign.jar:/opt/Java/jre/lib/jsse.jar:/opt/Java/jre/lib/jce.jar:/opt/Java/jre/lib/charsets.jar:/opt/Java/jre/classes  
Extension class path: /opt/Java/jre/lib/ext:/usr/Java/packages/lib/ext  
AppClassPath: .  
Boot CL: null  
App ClassLoader: sun.misc.Launcher$AppClassLoader@19134f4  

From this result we can clearly see what has been explained, the classpath of BootStrap is the "SDK" of Java, the ExtClassLoader is the directory of extensions and the AppClassLoader is the last in the argument in cli, if case it has not been passed, it assumes that it is the local directory:., or the one read from the jar's manifest. We can also see that who loaded our main class was AppClassLoader.

Well, you may have guessed by now that only these three CL are pre-defined and so we can add and change classloaders in that tree. This ensures flexibility and isolation of code, something widely used in application servers such as JBoss and Glassfish. The server will isolate each request creating classloaders so that a request is not visible in the "tree" of another; this ensures a great robustness and security platform.

Another great example of classloaders handling is the static scope of a variable. A variable has its static scope, that is, visibility, of the CL that was loaded down. Here's an example in Listing 3.

Listing 3. Analyzing a variable scope.

public class StaticScope {  
   public static int instanceCount=0;  
   public StaticScope() {  
      System.out.println("Value of instance:" + ++instanceCount);  
   public static void main (String args[]) throws Exception {  
      new StaticScope();  
        // Let's create a new Cl and put it below bootstrap.
       // Consequently the static variable will be different there
       // than specified.  
      URL urlArray={new File(System.getProperty("user.dir")).toURL() };  
      URLClassLoader cl=new URLClassLoader(urlArray, null);  


$ Java StaticScope 
Value of instance:1  
Value of instance:1  

What you did can be seen in the image shown in Figure 2.

Figure 2. Final hierarchy with Static Scopes.

The problem is that the static variable is not defined in the path defined by the other CL, then it is considered a new "scope".

So one of the problems that may arise is, as I carry a request in different classloaders and so that they have no CL in common, all are children of null, how to ensure the code visibility along the JVM? We know that all, directly or indirectly, have a CL in common, the bootstrap CL (null). However, that CL only carries the runtimes of the Java platform by default. Few know that we can edit, add, and overwrite the classpath of BootStrap. You can even override the implementation of a class that does not like the JDK, as the implementation of the stack, etc. In conclusion, the idea is to extend the visible jars to this adding the files you want to be visible in the entire JVM. This is done using the X options (extended) of the JVM (Listing 4).

Listing 4. Adding the X options.

$ Java -X  
    -Xmixed           mixed mode execution (default)  
    -Xint             interpreted mode execution only  
                      set search path for bootstrap classes and resources  
                      append to end of bootstrap class path  

As said earlier, you can override (-Xbootclasspath) or add at the beginning (/p to prefix) or at the end (/p to append) jars to the Bootstrap classpath. You can even override the JDK classes. Here's an example:

Copy the file of jdk source (java/lang) and modify its constructor, just like in Listing 5.

Listing 5. file

public class Integer {  
    public Integer(int value) {  
      System.out.println("I will divide your int by 2");  
      System.out.println("BEFORE VALUE: " + value + " AFTER VALUE " + value/2 + "\n");  
      this.value=value / 2;  

Create a temporary directory, such as ~/temp and create a ~/temp/java/lang. Note that ~ is the user's home directory. Compile the file and copy your .class to the following directory: ~/temp/java/lang. Now let's do a simple test.

Listing 6. file

public class Test {  
   public static void main(String args[]) {  
      new Integer(33);  

Compile and place this file in the directory ~/temp. Now run the following command line in Listing 7.

Listing 7. Running the test command.

$ java -Xbootclasspath/p:. Test  
I will divide your int by 2
I will divide your int by 2
I will divide your int by 2

I will divide your int by 2

Let's call now without modifying the bootstrap classpath (Listing 8).

Listing 8. Calling without modifications.

$ Java Teste  

The JVM itself when starts, also performs some calls creating new Integers, as we can see. But the major result is that the current directory, represented by ., was pre-set in the classpath BootStrap and the normal JDK Integer was not called. This ensures great flexibility because we can easily change any implementation unwanted in JDK. Some hackers modify versions of the System class once the getEnv method to get the user PATH was downgraded once and could not call it until recently. But the main idea is that we can easily secure a global scope class in the JVM putting your jar or .class in the classpath list of BootStrap.

Julio is a System analyst and enthusiast of Information Technology. He is currently a developer at iFactory Solutions company, working in the development of strategic systems, is also a JAVA instructor. He has knowledge and experi...

What did you think of this post?
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!

> More info about MrBool Credits
You must be logged to download.

Click here to login