Thursday, March 14, 2013

Java Classloaders



If someone asks you what class loaders are, you would probably say with a smile on your face, well!! they load classes in to JVM. And you would probably go on to explain what the perm gen space is and how it would run out if you got too many classes hogging it. It's not serious business, you might think, the chances are that you have gone through all your life not intefering with them. Its like that weird kid in the class, you don't mess with. He does his business you do yours, but sooner or later you gonna have to talk to him. Well class loaders are like that.

How many times have you hot deployed a web application and gotten the dreaded out of memory error, and how many times have you cursed before restarting to get it working again. Well the problem I am afraid does not lie in the application server (obviously), its how you have written your code. Do you ever look to see what the problem really is, well most people choose not to.

Now before we go any further let's see what class loaders do.

Class loaders do a pretty important job, when you compile your application you turn your java code into bytecode and save it in .class files, you go a step further and bind your .class files in to a jar. That's all good. Now when you want to use the classes in this jar file, you invariably add it to the class path of the application in question. And viola, you can use those classes in your application now. What happens here is not magic. Your .class files are, behind the scenes being loaded on to the JVM by classloaders.

Let’s see when classes are being loaded in to JVM.

Classes are loaded when you create instances of them, or when you make a static reference using a dot notation, loading classes is done on demand. Curious minds would inquire now how the references classes are loaded, well they are loaded along with your main class, but what about when you have multiple classes declaring instances of the same class, well class loaders keep caches of the classes they load hence if the class you require is already loaded they won’t load it again there's a catch here though. This brings us to an interesting revelation, how does the situation change when you have multiple class loaders. Multiple unrelated (isolated) class loaders can load the same class so that it’s possible for multiple instances of the same class to exist in the JVM and the funny thing is they will never be equal.

You might ask, what of that singleton class I wrote last week, I was so proud of, well what of it, your singletonness is guaranteed only to the class loader that loads it. How to protect your singleton from being loaded twice in to JVM by multiple class loaders is a question that begs a separate blog post. In short you basically need to write your own class loader or make sure you always chain your custom class loaders so that they always have a common parent.

Let’s now move on to types of class loaders in Java of which there are mainly three.
  1.            Bootstrap Class Loader
  2.            Extensions Class Loader
  3.            System Class Loader
Bootstrap class loader loads Java Core classes typically present in jre/lib folder, while extensions class loader as you may have guessed already load Java extensions typically present in jre/lib/ext you can also define your ext locations by setting the system property “java.ext.dir”. Systems class loader loads classes from the class path defined, you can also define this using “java.class.path” System variable.

And of course you can write your own custom class loaders, do this if you are pretty finicky, well most Java geeks like to be very hands-on. What you also need to understand is that these class loaders are executed in the order listed, first the bootstrap, then extensions and finally system which is implemented by sun.misc.Launcher$AppClassLoader.

 When Java code is compiled by the compiler, the complier adds a static final field called “class”, every class has it. And why I brought this seemingly irrelevant subject here is because using this property you can get the class loader which loaded the class, this is pretty handy. You can try this out with a class you wrote, the interesting this to note here that you can go up the hierarchy to access the parent class loaders, when you get null, is when you know you have hit the bootstrap class loader, because bootstrap class loader always returns null.

Before I wrap this post up, let me list the steps a class loader has to go through before loading a class in to JVM, important if you are writing your own

1.     Verify Class Name


Important if you write your own class loader, you don’t want people to use your class loader to load classes you didn’t intent to.

2.     Check to see if it has been loaded already


If the class is loaded, which it tracks by using a map of some sort, return the class already loaded

3.     Check to see if the class is a systems class


If it is then the chances are that it’s already loaded, don’t take chances through, pass control to your parent class loader.

4.     Attempt to fetch the class from the class loader repository


This is where the actual loading happens, your repository may reside over a network, or a separate folder, load your classes as a byte stream.

5.     Define the class for the JVM


First step is to verify that the byte code is valid, if not throw a class format error

6.     Resolve the class


 What this means is that you need to load the references (any classes that the class you are trying load is using) you also need to verify the legitimacy of these references, failing this step is what leads to the infamous Linkage Errors

7.     Return the class to the caller


Finally return your class to the caller. Ill show you in another post how to write your own class loader.

And that’s a wrap.


5 comments:

  1. Very nice introduction to the world of class loading. Loved the way you have presented it. Keep it up.

    ReplyDelete
  2. Very good and informative post. But leaves few questions:
    1. If there are multiple class loaders, how JVM decides which class loader to use?
    2. If a class is loaded multiple times by different unrelated class loaders, and if an instance is created then which class would be used?

    ReplyDelete
    Replies
    1. Hello Ashish thanks for your comment. Your questions are partially answered here http://ruchirabandara.blogspot.sg/2013/03/custom-class-loaders.html . If you are still a little hazy on the subject.
      1. You load your classes with your own classloader in the following fashion

      Class class1 = (Class) Class.forName( "com.sample.Main",true, classLoader);
      Object obj = class1.newInstance();
      Class[] paramString = new Class[1];
      paramString[0] = String.class;
      class1.getDeclaredMethod("doSomething", new Class[]{}).invoke(obj, args);

      2. You would get class cast exceptions if you do, jvm would not know which one to load.

      Delete
  3. What do you mean by "references classes"

    ReplyDelete
  4. It should be "Reference Classes", my mistake. They are the classes your main class references/uses. These include the classes in packages you import, classes you specifically import, static classes you reference by using dot notation. Things like that. I hope it's clear.

    ReplyDelete