Internals of Java Class Loading
Class loading is one of the most powerful mechanisms provided by the Java language specification. Even though the internals of class loading falls under the "advanced topics" heading, all Java programmers should know how the mechanism works and what can be done with it to suit their needs. This can save time that would otherwise have been spent debugging
ClassNotFoundException
, ClassCastException
, etc.Class and Data
A class represents the code to be executed, whereas data represents the state associated with that code. State can change; code generally does not. When we associate a particular state to a class, we have an instance of that class. So different instances of the same class can have different state, but all refer to the same code. In Java, a class will usually have its code contained in a .class file, though there are exceptions. Nevertheless, in the Java runtime, each and every class will have its code also available in the form of a first-class Java object, which is an instance of
java.lang.Class
. Whenever we compile any Java file, the compiler will embed a public, static, final field named class
, of the type java.lang.Class
, in the emitted byte code. Since this field is public, we can access it using dotted notation, like this:java.lang.Class klass = Myclass.class;
Once a class is loaded into a JVM, the same class (I repeat, the same class) will not be loaded again. This leads to the question of what is meant by "the same class." Similar to the condition that an object has a specific state, an identity, and that an object is always associated with its code (class), a class loaded into a JVM also has a specific identity, which we'll look at now.
In Java, a class is identified by its fully qualified class name. The fully qualified class name consists of the package name and the class name. But a class is uniquely identified in a JVM using its fully qualified class name along with the instance of the
ClassLoader
that loaded the class. Thus, if a class named Cl
in the package Pg
is loaded by an instance kl1
of the class loader KlassLoader
, the class instance of C1
, i.e. C1.class is keyed in the JVM as (Cl, Pg, kl1)
. This means that the two class loader instances (Cl, Pg, kl1)
and (Cl, Pg, kl2)
are not one and the same, and classes loaded by them are also completely different and not type-compatible to each other.Java Class Loader
A Delegation Model (version 1.2 onwards) is used for loading class to the JVM. Class Loaders are structured in java is in a way that at start-up time the JVM doesn’t need to know anything about the classes that will be loaded at run time. Class loaders mainly perform two functions. First, when the VM needs to load the byte code for a class, it asks a class loader to find the corresponding byte code. Each class loader will use their own method to find the requested byte code (class),then it loads it from the local disk or fetch them across the Net using any protocol including other classes and interfaces are loaded as they referenced in the byte code being executed, the main class . Then it creates an instance of the java.lang.Class of loaded byte code. This makes the class become available to the JVM for execution. Second, class loaders define the name spaces seen by different classes and how those name spaces relate to each other.
Delegation Model
In delegation model, the class loaders has hierarchical order forming a tree structure,the bootstrap class loader as the root of this tree.Bootstrap Class Loader.
Java core API classes, which are essential at the JVM load are loaded by the bootstrap (often known as primordial) Class Loader. This class loader loads the class files from local file system using the file accessing options of current OS to open/read. It’s read the class files in the form of byte arrays, providing essential resources on the JVM start up. Sometimes this Class Loader is referred as the “internal” class loader or the “default” class loader also.
Extension class loader
The extension class loader is primary responsibility to load classes from the extension directories and provides ability to simply drop in new JVM extensions, without requiring modification to the user’s classpath.
System Class Loader
The Application-specific classes are loaded by the system (often known application) Class Loader.
If all the class loader failed to load the required class, it will generate a java.lang.ClassNotFoundException else a java.lang.NoClassDefFoundError . There is a parent -child relationship is maintained by these class loaders, except boot strap class loader these class loaders has a parent.
The delegation model follows these steps when the client request for a particular class.
1. JVM first check whether the requested class has already been loaded (JVM caches all the classes that are loaded) by the any Class Loader. If yes, the class is returned.
2. If the class is not loaded, the request is forwarded to the parent Class Loader. This delegation will go up to the bootstrap Class Loader.
3. If the delegation failed to load the class , then current Class Loader will search for the requested class. In its defined locations .
4. If the class loading failed, it will generate a java.lang.ClassNotFoundException .
The Java class loader architecture provide a large amount of flexibility for developers in the application is assembling and extension process.
Phases of class loading
There are three phases of concrete class loading: physical loading, linking, and initializing.
1. In in first phase of physical loading required class file will be searched in specified classpaths. If the file is found it is read and the byte code is loaded. This process gives a basic memory structure to the class object, such concepts like methods, fields, and other referenced classes are not known at this stage.
1. Linking can be broken down into three main stages, because it is complex phase:
- Bytecode verification through class loader, which executes a number of checks on the bytecodes.
- Class preparation. This stage prepares the necessary data structures that represent fields, methods and implemented interfaces that are defined within the class.
- Resolving of all the other classes referenced by a particular class. The classes can be referenced in a number of ways:
- Superclasses
- Interfaces
- Field types
- Types in method signatures
- Types of local variables used in methods
It is interesting, that class loading can be performed in a lazy manner and therefore some parts of the class loading process may be done on first use of the class rather than at load time.
Exceptions
The biggest challenge in dealing with class-loading problems is that problems rarely manifest themselves during the class-loading process but rather during the usage of a class later on. In following shown two class loading related exceptions, with potential causes
· ClassNotFoundException
- An archive, directory, or other source for the classes was not added to the class loader asked to load the class, or to its parent.
- A class loader’s parent is not set correctly.
- The wrong class loader is used to load the class in question.
· NoClassDefFoundError
- An archive, directory, or other source for the classes was not added to the class loader asked to load the class, or to its parent.
- A class loader’s parent is not set correctly.
- Symbolic links in a class are inaccessible by the containing class’s class loader, such as a child class loader.
No comments:
Post a Comment