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..