Monday 10 June 2019

How to load two versions of same class in same virtual machine?


In some situations, you may want to load two versions of same class, you can do that by using class loaders.




As you see above image, class loader 1 loads version 1 of class, whereas class loader 2 loads version 2 of class.

Class.forName
public static Class<?> forName(String name,boolean initialize, ClassLoader loader)
forName method loads given class using the classloader specified by user.

Below step-by-step procedure helps you to develop an application that loads two versions of same class.

Step 1: Create version1.jar file.
Define ProductInfo class by following below directory structure.

$tree
.
└── com
    └── sample
        └── app
            └── model
                └── ProductInfo.java

4 directories, 1 file


ProductInfo.java
package com.sample.app.model;

public class ProductInfo {
 
 static {
  System.out.println("Loading version 1 of the class");
 }
 
 public String toString() {
  return "Version 1 of the class is loaded";
 }

}

Compile ProductInfo.java by executing below command.

javac com/sample/app/model/ProductInfo.java

$javac com/sample/app/model/ProductInfo.java 
$
$tree
.
└── com
    └── sample
        └── app
            └── model
                ├── ProductInfo.class
                └── ProductInfo.java

4 directories, 2 file

Execute below command to generate version1.jar file.

jar -cvf version1.jar *
$jar -cvf version1.jar *
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/sample/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/(in = 0) (out= 0)(stored 0%)
adding: com/sample/app/model/ProductInfo.class(in = 559) (out= 357)(deflated 36%)
adding: com/sample/app/model/ProductInfo.java(in = 211) (out= 151)(deflated 28%)
$
$tree
.
├── com
│   └── sample
│       └── app
│           └── model
│               ├── ProductInfo.class
│               └── ProductInfo.java
└── version1.jar

4 directories, 3 files

Step 2: Create version2.jar file.

Update productInfo.java file like below.

ProductInfo.java
package com.sample.app.model;

public class ProductInfo {
 
 static {
  System.out.println("Loading version 2 of the class");
 }
 
 public String toString() {
  return "Version 2 of the class is loaded";
 }

}

Compile ProductInfo.java.

Create version2.jar by executing below command.
jar -cvf version2.jar *

Step 3: Create App.java file that loads the classes using URLClassLoader.
Below snippet loads the ProductInfo class from version1.jar file.

URL url1 = new URL("file:/Users/krishna/Documents/TechnicalDocuments/Java/examples/classloading/version1.jar");
URLClassLoader classLoader1 = new URLClassLoader(new URL[] { url1 });
Class clazz1 = Class.forName("com.sample.app.model.ProductInfo", true, classLoader1);
Below snippet loads the ProductInfo class from version2.jar file.
URL url2 = new URL("file:/Users/krishna/Documents/TechnicalDocuments/Java/examples/classloading/version2.jar");
URLClassLoader classLoader2 = new URLClassLoader(new URL[] { url2 });
Class clazz2 = Class.forName("com.sample.app.model.ProductInfo", true, classLoader2);


App.java
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class App {

 public static void main(String args[])
   throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
  URL url1 = new URL(
    "file:/Users/krishna/Documents/TechnicalDocuments/Java/examples/classloading/version1.jar");
  URLClassLoader classLoader1 = new URLClassLoader(new URL[] { url1 });

  URL url2 = new URL(
    "file:/Users/krishna/Documents/TechnicalDocuments/Java/examples/classloading/version2.jar");
  URLClassLoader classLoader2 = new URLClassLoader(new URL[] { url2 });

  Class clazz1 = Class.forName("com.sample.app.model.ProductInfo", true, classLoader1);
  Class clazz2 = Class.forName("com.sample.app.model.ProductInfo", true, classLoader2);

  Object obj1 = clazz1.newInstance();
  Object obj2 = clazz1.newInstance();

  System.out.println(obj1);
  System.out.println(obj2);

 }
}

Compile and run App.java, you can see below messages in console.
Loading version 1 of the class
Loading version 2 of the class
Version 1 of the class is loaded

Version 1 of the class is loaded


Previous                                                 Next                                                 Home

No comments:

Post a Comment