用自定义类加载器加载类,每次用一个classloader实例来加载,每次加载的class都是最新的,可以实现类的热加载,但类的静态变量也每次都是初始值,如下例子:
// 自定义classloader, 来自《深入理解java虚拟机》一书
class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if(is == null) {
return super.loadClass(name);
}
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (Exception e) {
throw new ClassNotFoundException();
}
}
}
// 加载Test类
public class ClassLoadTest {
public static void main(String []args) throws Exception {
while(true) {
Object obj = new MyClassLoader().loadClass("com.java.load.Test").newInstance();
System.out.println(obj.getClass().getClassLoader());
LoadInterface c = (LoadInterface)obj;
c.method1();
Thread.sleep(10000);
}
}
// 调用上下文classloader,加载类并返回
public Object getObject(String className) throws Exception, IllegalAccessException, ClassNotFoundException {
System.out.println("test1: " + ClassLoadTest.class.getClassLoader());
System.out.println("test2: " + Thread.currentThread().getContextClassLoader());
Object obj = Thread.currentThread().getContextClassLoader().loadClass(className).newInstance();
return obj;
}
}
public class Test {
private static int a = 1;
public void method1() {
System.out.println("this is method1 in test11");
System.out.println(a++);
}
public static void main(String []args) throws Exception, ClassNotFoundException, Exception {
while(true) {
Object obj = new ClassLoadTest().getObject("com.java.load.Test");
Test t = (Test)obj;
t.method1();
Thread.sleep(10000);
}
}
}
上例中,执行ClassLoadTest,每次MyClassLoader实例对象都不一样,打印出来的值a一直是1,如果修改Test类中method1方法,打印信息也会改变。
将ClassLoadTest.class放在JRE的ext/classes下,让ext classloader去加载,执行Test类方法时,ClassLoadTest的classloader一直是ExtClassLoader的同一个实例对象,Test的classloader一直是AppClassLoader的同一个实例对象。Test被同一个classloader加载。
浙公网安备 33010602011771号