基于Java 类加载原理实验类动态替换

一个小实验,基于对Java类加载模型的理解,实现一个Java类动态替换的效果,仅供学习理解Java类加载机制。
关键:
(1)JVM通过类的加载器和类全名组合识别一个类。
(2)类加载器层次结构及委托加载模型
(3)自定义类加载器

示例:
(1)定义一个服务接口及其实现类:AService 和 SimpleA,提供简单的add服务。
AService

package org.demo;

public interface AService {

public int add(int a, int b);
}


SimpleA

package org.demo;

public class SimpleA implements AService {

@Override
public int add(int a, int b) {
int result = 0;
result = a + b;
return result;
}

}


(2)自定义类加载器HotreplaceLoader,加载示例中需要动态替换的类

package org.demo;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

public class HotreplaceLoader extends ClassLoader {

public HotreplaceLoader(){
super(null);
}

@Override
protected Class findClass(String name) throws ClassNotFoundException {
byte[] data = loadClassData(name);
return this.defineClass(name, data, 0, data.length);
}

public byte[] loadClassData(String name) {
try {
name = name.replace(".", "//");
FileInputStream is = new FileInputStream(new File(
"E:\\loadclass\\src\\" + name + ".class"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ((b = is.read()) != -1) {
baos.write(b);
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class cls = null;
cls = findLoadedClass(name);
if(!name.equals("org.demo.SimpleA") && cls == null){
cls = getSystemClassLoader().loadClass(name);
}else{
try{
cls = findClass("org.demo.SimpleA");
}catch(Exception e){
e.printStackTrace();
}
}
if (cls == null)
throw new ClassNotFoundException(name);
if (resolve)
resolveClass(cls);
return cls;
}

}


(3)主进程Worker,无限循环加载目标类,并调用其服务,每次调用后休息

package org.demo;

import java.lang.reflect.Method;

public class Worker {

public static void main(String[] args) throws Exception{
for(;;){
HotreplaceLoader loader = new HotreplaceLoader();
Class cls = loader.loadClass("org.demo.SimpleA");
//Object aService = cls.newInstance();
//Method m = aService.getClass().getMethod("add", new Class[]{int.class, int.class});
//Object count = m.invoke(aService, new Object[]{1, 1});
AService as = (AService)cls.newInstance();
int count = as.add(1, 1);
System.out.println(String.valueOf(count));
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}

}


(4)验证
执行主进程,控制台不断打出“2”。
修改SimpleA 源码为:

public class SimpleA implements AService {

@Override
public int add(int a, int b) {
int result = 0;
result = (a + b)*2;
return result;
}

}

然后将编译好的字节码SimleA.class,拷贝到设定的加载目录E:\loadclass\src\替换原来的字节码文件。
控制台变化,不断打出“4”。


参考:
Java 类的热替换 —— 概念、设计与实现
http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/

你可能感兴趣的:(core,java)