Let us discuss how to load multiple versions of a class into a single JVM using custom classloader.
Suppose we have a support class SupportClass with two different versions.We can select the required version of SupportClass at runtime.
File System looks as given below
where
SupportInterf.java
package support;
public interface SupportInterf {
public void displayVersion();
}
SupportClass.java ( Version 01)
package support;
public class SupportClass implements SupportInterf{
public void displayVersion(){
System.out.println("Class version is Version 01");
}
}
SupportClass.java (Version 02)
package support;
public class SupportClass implements SupportInterf{
public void displayVersion(){
System.out.println("Class version is Version 02");
}
}
We have to use a custom classloader , FileSystemClassLoader to load both the versions of the SupportClass into the jvm.
FileSystemClassLoader.java
package loader;
import java.io.*;
import java.net.URL;
import java.util.Enumeration;
import support.SupportInterf;
public class FileSystemClassLoader extends ClassLoader {
private String currentRoot = null;
public FileSystemClassLoader() throws FileNotFoundException {
this(FileSystemClassLoader.class.getClassLoader(), System
.getProperties().getProperty("java.home"));
}
public FileSystemClassLoader(String root) throws FileNotFoundException {
this(FileSystemClassLoader.class.getClassLoader(), root);
}
public FileSystemClassLoader(ClassLoader parent)
throws FileNotFoundException {
this(parent, System.getProperties().getProperty("java.home"));
}
public FileSystemClassLoader(ClassLoader parent, String root)
throws FileNotFoundException {
super(parent);
File f = new File(root);
if (f.isDirectory()) {
currentRoot = root;
} else {
throw new FileNotFoundException();
}
}
public void execute(String codeName) {
Class klass = null;
try {
klass = findClass(codeName);
SupportInterf task = (SupportInterf) klass.newInstance();
task.displayVersion();
} catch (Exception exception) {
exception.printStackTrace();
}
}
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 URL findResourceURL(String resourceName) {
return null;
}
public java.util.Enumeration findResourcesEnum(String resourceName) {
return null;
}
public String findLibraryPath(String libraryName) {
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);
}
}
}
Let us create a Main class to load SupportClass using the above FileSystemClassLoader .I have used Eclipse for it.See the package structure of
Eclipse project custom_classloader .
where
Main.java
package main;
import java.io.FileNotFoundException;
import loader.FileSystemClassLoader;
public class Main {
/**
* @param args
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
String v01classpath="/home/radhakrishnan/customloader/supportV01";
FileSystemClassLoader loader4v01=new FileSystemClassLoader(v01classpath);
loader4v01.execute("support.SupportClass");
String v02classpath="/home/radhakrishnan/customloader/supportV02";
FileSystemClassLoader loader4v02=new FileSystemClassLoader(v02classpath);
loader4v02.execute("support.SupportClass");
}
}
SupportInterf.java
package support;
public interface SupportInterf {
public void displayVersion();
}
The Output of the above program is:
Class version is Version 01
Class version is Version 02
Please visit ClassLoader & Usage of Custom ClassLoader to study more about class loaders.
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.Suppose we have a support class SupportClass with two different versions.We can select the required version of SupportClass at runtime.
File System looks as given below
where
SupportInterf.java
package support;
public interface SupportInterf {
public void displayVersion();
}
SupportClass.java ( Version 01)
package support;
public class SupportClass implements SupportInterf{
public void displayVersion(){
System.out.println("Class version is Version 01");
}
}
SupportClass.java (Version 02)
package support;
public class SupportClass implements SupportInterf{
public void displayVersion(){
System.out.println("Class version is Version 02");
}
}
We have to use a custom classloader , FileSystemClassLoader to load both the versions of the SupportClass into the jvm.
FileSystemClassLoader.java
package loader;
import java.io.*;
import java.net.URL;
import java.util.Enumeration;
import support.SupportInterf;
public class FileSystemClassLoader extends ClassLoader {
private String currentRoot = null;
public FileSystemClassLoader() throws FileNotFoundException {
this(FileSystemClassLoader.class.getClassLoader(), System
.getProperties().getProperty("java.home"));
}
public FileSystemClassLoader(String root) throws FileNotFoundException {
this(FileSystemClassLoader.class.getClassLoader(), root);
}
public FileSystemClassLoader(ClassLoader parent)
throws FileNotFoundException {
this(parent, System.getProperties().getProperty("java.home"));
}
public FileSystemClassLoader(ClassLoader parent, String root)
throws FileNotFoundException {
super(parent);
File f = new File(root);
if (f.isDirectory()) {
currentRoot = root;
} else {
throw new FileNotFoundException();
}
}
public void execute(String codeName) {
Class klass = null;
try {
klass = findClass(codeName);
SupportInterf task = (SupportInterf) klass.newInstance();
task.displayVersion();
} catch (Exception exception) {
exception.printStackTrace();
}
}
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 URL findResourceURL(String resourceName) {
return null;
}
public java.util.Enumeration findResourcesEnum(String resourceName) {
return null;
}
public String findLibraryPath(String libraryName) {
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);
}
}
}
Let us create a Main class to load SupportClass using the above FileSystemClassLoader .I have used Eclipse for it.See the package structure of
Eclipse project custom_classloader .
where
Main.java
package main;
import java.io.FileNotFoundException;
import loader.FileSystemClassLoader;
public class Main {
/**
* @param args
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
String v01classpath="/home/radhakrishnan/customloader/supportV01";
FileSystemClassLoader loader4v01=new FileSystemClassLoader(v01classpath);
loader4v01.execute("support.SupportClass");
String v02classpath="/home/radhakrishnan/customloader/supportV02";
FileSystemClassLoader loader4v02=new FileSystemClassLoader(v02classpath);
loader4v02.execute("support.SupportClass");
}
}
SupportInterf.java
package support;
public interface SupportInterf {
public void displayVersion();
}
The Output of the above program is:
Class version is Version 01
Class version is Version 02
Please visit ClassLoader & Usage of Custom ClassLoader to study more about class loaders.
No comments:
Post a Comment