When JVM starts it starts the class loaders and generates the state for the code present in .class files
- On top level, we have BootStrap Class Loader
- Loads classes present in run time jar i.e., jre/lib/rt.jar (java.lang.Object, java.lang.String etc)
- It has native implementation and we can't get the details of it
- java.lang.String.getClass.getClassLoader() would return null
- On the next level, we have Ext Class Loader
- Used to load classes in java.ext.dirs path.
- We can add our own jars to ext directory and get them loaded through Ext Class Loader
- Third Level has App Class Loader
- Used to load the classes mentioned in class path
JVM stores the classes with the below understanding - (class name, package name, class loader instance).
- So when we have a Target class present in our application and is loaded by two different class loaders - ClassLoader1 and ClassLoader2, doing a casting of instances of Target class loaded by these two different ClassLoader1 and 2 (say target1 casted to target2) will result in ClassCastException
- When same class is loaded by "two different instances" of same class loader also results in ClassCastException when we are casting target2 to target1
- Static variables are loaded once for each and every instance of class loader!
- In order to get the classloader for a given thread, we have getContextClassLoader() in java.lang.Thread class
- When ever a java class is compiled to class file, JVM injects the final static variable java.lang.Class klass=MyClass.class into the byte code of class file
- We can have our own custom class loaders by extending the ClassLoader class.
- At times we can have two classes with same name and same package structure stored in different file structures on the same system and loaded by the same class loader - in these instances generally the class found first in the class path gets loaded. If at all we want the second one to load rather the one declared first in class path, we can create our own custom class loader that takes the directory structure through property file and then load the byte code of class file by using the file input stream and directory path.
public class Client{
public static void main (String[] args){
try{
byte[] code = getClassDefinition
("client.TaskImpl");
serverIntf.execute("client.TaskImpl",
code);
}
catch(RemoteException remoteException){
remoteException.printStackTrace();
}
}
private static byte[] getClassDefinition
(String codeName){
String userDir = System.getProperties().
getProperty("BytePath");
FileSystemClassLoader fscl1 = null;
try{
fscl1 = new FileSystemClassLoader
(userDir);
}
catch(FileNotFoundException
fileNotFoundException){
fileNotFoundException.printStackTrace();
}
return fscl1.findClassBytes(codeName);
}
public byte[] findClassBytes(String className){
try{
String pathName = currentRoot +
File.separatorChar + className.
replace('.', File.separatorChar)
+ ".class";
FileInputStream inFile = new
FileInputStream(pathName);
byte[] classBytes = new
byte[inFile.available()];
inFile.read(classBytes);
return classBytes;
}
catch (java.io.IOException ioEx){
return null;
}
}
public Class findClass(String name)throws
ClassNotFoundException{
byte[] classBytes = findClassBytes(name);
if (classBytes==null){
throw new ClassNotFoundException();
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}
public Class findClass(String name, byte[]
classBytes)throws ClassNotFoundException{
if (classBytes==null){
throw new ClassNotFoundException(
"(classBytes==null)");
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}
public void execute(String codeName,
byte[] code){
Class klass = null;
try{
klass = findClass(codeName, code);
TaskIntf task = (TaskIntf)
klass.newInstance();
task.execute();
}
catch(Exception exception){
exception.printStackTrace();
}
}
- ClassLoader loads a class only once. Any identical class if loaded second gets cached copy of first and thus the second loaded class is lost
- ClassLoader must have a parent class loader except for boot strap class loader
- Class loaders must delegate the loading the class duty to parents first before attempting to load the class themselves
Eclipse has it's own class loader (org.eclipse.core.internal.boot.PlatformClassLoader) loaded by the boot strap class loader. This PlatformClassLoader instantiates the individual plugin class loaders (org.eclipse.core.internal.plugins.PluginClassLoader) for each plugin.
References:
- O'Reilly Onjava - http://goo.gl/GrC4a
- Dr Dobbs - http://goo.gl/v670w
0 comments:
Post a Comment