... continuation of last post
TO
understand the working of class loader , the following method is an important
an important method.
protected synchronized Class<?>loadClass(String
name,boolean resolve) throws ClassNotFoundException :
This method loads the class with the specified
binary name. It has default implementation which searches for the class in
following order:
- It invokes findLoadedClass(String) to check if class has been already loaded.
- Invoke loadClass(String) method on parent classloader, if parent classloader is null then classloader built in jvm is used.
- Invoke findClass(String) method to find the class.
To set the parent class loader, we have two ways to
do so in the ClassLoader constructor:
public class MyClassLoader extends ClassLoader{
public MyClassLoader(){
super(MyClassLoader.class.getClassLoader());
}
}
or
public class MyClassLoader extends ClassLoader{
public MyClassLoader(){
super(getClass().getClassLoader());
}
}
The reason to write a custom class loader in java:
- It is required when we want to load the class from alternative repositories: This is the most common case, in which an application developer might want to load classes from other locations, for example, over a network connection.
- It is required when we want to partition the user code:This case is not frequently used by application developers, but widely used in servlet engines.
- It allows unloading of classes: As classloader maintains a cache of the classes that it has loaded, so these classes can not be unloaded until the classloader itself has been dereference. due to this reason ,system and extension classes are never unloaded, but application classes can be unloaded when there classloader is derefernce.
- It helps to create the namespace: As jvm recognizes the class by the class name + name of classloader, so we can have have multiple copies of the same class across different classloaders .
- In this case there has been variation with the release of jdk version, with java1, we need to subclass the ClassLoader class as it is abstract class and the =n override the loadClass() method.
- Then loadClass() has to fulfill various requirements like :
- check weather class has been previously loaded.
- check weather class has been loaded by system class loader.
- loading the class.
- linking the class.
- resolving the class.
- returning the class to the caller
- In Java2 the ClassLoader class has been given a new constructor that takes parent class loader as a parameter .
- the parent classloader parameter can be application classloader or can be any user-defined class loader.
- Having this changes helps to follow delegation model very well .
- Under the delegation model, the loadClass() method is no longer abstract, and as such does not need to be overridden. The loadClass() method handles the delegation class loader mechanism and should not be overridden.
- custom class loaders should override only the new findClass() method, in which the code to access the new class repository should be placed. The findClass() method is responsible only for loading the class bytes and returning a defined class. The method defineClass() can be used to convert class bytes into a Java class:
class NetworkClassLoader extends
ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
}
}
NameSpace:
- In java each classloader has its own namespace, means a single application can load multiple types with same fully qualified name.
- But some times full qualified name is not enough to identify the class inside the jvm, so in that case namespace comes into existence.
- If multiple types of that same name have been loaded into different name spaces, the identity of the classloader that loaded the type (the identity of the name space it is in) will also be needed to uniquely identify that type.
- Inside the jvm namespace arise as a result of resolution phase.
- As part of the data for each loaded type, the Java virtual machine keeps track of the class loader that imported the type.
- When the virtual machine needs to resolve a symbolic reference from one class to another, it requests the referenced class from the same class loader that loaded the referencing class.
If the parents fail to load the class, it will
come down to the current ClassLoader 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 .
So, its handy you remember this when you write your own classloader Lookup sequence:
CACHE (this.findLoadedClass()) >>> PARENT(super.loadClass()) >>> DISK(this.findClass() and then this.loadClass()).
No comments:
Post a Comment