Over the next few days I will post on Classloading, Classloaders, Debugging, and Debugging (the more you do, the more you'l learn) ..
The JVM spec defines LOADING like this (take a deep breath!) :
"Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler and constructing, from that binary form, a Class object to represent the class or interface. The binary format of a class or interface is normally the class file format"
If almost everything in Java is an object , then there should be a class from where this object came from. A simpler chicken and egg problem you say :)
One of the most oft talked about aspects of Java programming is the Classloading ( i will use the terms 'classloading' and 'loading' interchangeably - both intended to describe the same act )
If you have a huge application, with classloading, you probably have one less thing to worry about.
Classloading in Java is achieved by an entity called the Classloader. A classloader takes in the raw bytes from a .class file , standard Java api's provided with the SDK (or) any other custom classes required by your class file and then creates the right bytecodes to eventually run your .class file.
Classloading is a blanket term used to describe the process of reading .class file and executing it. Behind the scenes, the classloader does much more than just "loading".
We have three main stages:
LOADING -> LINKING -> INITIALIZING
The very first step - read the .class bytes into the JVM process memory.
All the "under the hood" stuff a JVM does for the class to mean something to it. This stage involves three mini steps:
i) verifying the bytecodes of the class for a "lot" of things - VERIFICATION
ii) building up JVM internal data structures to store the class entities in a way the JVM finds - PREPARATION (method table strikes a chord?)
iii) the previous step had built up the data structures with relative offsets and symbol references - in this step we "resolve" - RESOLUTION
The revered <clinit> for a class is run. And your static fields of a class are finally set up to user defined values(if any).
Dear Programmer.. we have take off! Go ahead and create an instance of this class.
This is from JVM perspective. What about the one who initiates this - the classloader ?
Some background on the "much loved" classloader (let me abbreviate it as CL)
All , except the primordial/bootstrap CL, must have a parent - which makes it abide by the "Parent Delegation Model"
How the delegation model looks like?
User defined CL1 , User defined CL2
Bootstrap CL looks for classes in the bootclasspath (sdk/jre/lib/rt.jar, vm.jar etc) : -Xbootclasspath:...
Extension CL looks for classes in the jre/lib/ext directory of the SDK
Application CL looks for classes on $CLASSPATH (on *nix machines) / %CLASSPATH% (on Win) or directories/classes pointed by -classpath option
User defined CL's look for classes on , well, the user defined class path(s) (think of the URLClassLoder .. )
What is the need for a delegation model?
1) With Parent Delegation, you "always" ask your parent to try and load the class
2) The higher you go, the more trusted the classloader is by the JVM (there is a *caveat, let me dwell on that later)
3) The lower you come , the more "places" your classloader is allowed/designed to scout for classes to load
4) Security. Period. (probably is the crux of the above points)
With this kind of a delegation, you make one thing sure - you are loading the right class .
Say you have your own implementation of java.lang.String class.
Place it in the classpath
Run your app, say, HelloWorld, with a custom classloader MyClassloader to load the String class
Without parent delegation: you could probably force the classloading of your own implementation, rather than the more trusted one which comes with the SDK. In which case the chances of goofing up and crashing the JVM rises from 99-100% (i just made this up, but you get the point right?)
With parent delegation: sit back and enjoy while JVM go on with its usual business of asking bootstrap to load it from the RIGHT jar.
You could append/prepend custom JAR's to bootclasspath - thereby circumventing the "security" part of the CL and force JVM to somehow load your own version of the standard Java API's.
We do not recommend this at all - i myslef use it only for debug purposes. Reason? Remember the 99-100% .. i do not want to fall into an obvious pit as this. :)
Do not lose heart. If none of the three JVM provided CL's does the job for you , you could (and sometimes, should) write your own classloader.
There are tons of material on the web for "how and why you should write a custom classloader" . Gist of the "why" reasons:
1) With a custom classloader you can have many paths from where you can load a class - even from the web (applets)
2) In an enterprise app, you SHOULD have your own CL. This way , you need not put all jar's on the classpath (plus) you have the option of UNLOADING classes when not needed. (More on this later)
3) Create namespaces - have multiple copies of the same class across different classloaders - because the JVM recognizes your class by the classname + classloader name
I will post more on classloaders, classloading, EXCEPTIONS (who hasn't seen a NoClassDefFoundError / ClassNotFoundException in his programming life?) and much more in the coming days.
Happy Java week..
Java Technology Community
with Tags: hood X
SadanandaAithal 270001H7RR Tags:  the classloader hood classloading jvm under 1 Comment 2,775 Visits
Last time, I ended on Parent Delegation model and reasons for "Why you should have a custom classloader for your application". Let me dwell on this a bit:
In the delegation model, all custom classloaders sit beneath the Application Classloader. I mentioned that when there's a classload requested for a classloader, it should ask its parent to try and load it. Well, the guys who wrote all this magic (a.k.a classloading) thought - "how do we improve this process of 'parent delegation'? "
Answer to that is the Classloader cache.
Every classloader has its own cache - which would hold the "defined class structure" of every successful classload it has performed.
So let me change the parent delegation definition a bit now:
"when a classload is requested out of a CL, the CL should look for the class structure in its cache . If it finds one, use it. Else, delegate to the parent .. (and they can live happily-ever-after till CNFE doesn't surface!)"
How does it help? Well, the very first time for any class - parent delegation is a must .
If the parents fail to load the class, it will come down to the current CL itself. If it finds the class, it goes and stores it in its cache.
So the next time a classload is requested, and say , you found it in the cache - you can use it because you are assured that a parent delegation 'had' occurred sometime in the past for this class .
All is well.
So, its handy you remember this when you write your own classloader
CACHE (this.findLoadedClass()) >>> PARENT(super.loadClass()) >>> DISK(this.findClass() and then this.loadClass())
sample code :
So, the classloader cache certainly pips speed of the classloading sequence a bit (not to be confused with Shared Class Cache, which I hope to blog in few days time).
To lessen the tax on the system , the JVM also employs what is called as a Lazy Loading - meaning a classload is initiated at the following times only
i) creation of the first object of that class
ii) first instance of any of the subclasses of this class
iii) any of this class's static field is initialized
This way you are assured of classloads of only the required classes. Saves space , saves time.
(Its opposite number is the Eager classloading - recursive loading of all classes referenced in our application - and I believe is used in Real Time applications.. )
Few things on Class Unloading:
Comes into effect ONLY if there's a custom classloader in your application - because the other three classloader loaded classes are never unloaded.
A class and its classloader are linked through its JVM internal structures. So only when a classloader is out of scope for the JVM will that classloader's classes will be unloaded.
(for more on this, you should attend the webinars on "Understanding Java Memory Management" and "Debugging Classloader Memory Leaks in the WebSphere Application Server" as part of the Java Week)
CNFE , NCDFE and the other usual suspects are coming soon.. and also some of the debugging techniques we use to find " 'em goons" ..
Happy Java Week!