目录
1.概述
java是非动态语言,所谓的动态语言就是在代码运行的过程中可以动态的增加方法,类。java虽然非动态语言但是利用自己的反射,依旧可以完成这样的功能。 今天讨论的是java的热加载,也就是热更新。考虑这样一个事实,当你的项目代码十分繁重,或者说上线很麻烦的时候。这个时候能够在不重启项目的情况下,让我们修改的java代码生效,就是很好的事情了。 谁也不想动不动重新编译,重启项目。 要解决这个问题,就要用到java的类加载,也就也是自定义类加载。 而理解类加载的核心,就是理解Class<?>对象,这里的Class<?>对象不要理解成你new的那个对象,严格来说new的称为实例。 在java中,每一个Class源码最终会被编译成对应的.class文件, 而类加载在第一个阶段就会把这个class二进制文件载入内存生成对应的Class<?>对这象,这是类加载初始阶段的做的事情。 要实现热更新,只需要定期重新载入class二进制文件即可。
2.在此之前
你需要了解,双亲委派机制,java反射。以及Class<?>对象
3.目录结构如下
4.HotLoad代码
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
public class Hotload {
public static void main(String[] args)
throws ClassNotFoundException, InterruptedException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
while (true) {
System.out.println("111");
ClassLoader loader = new 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 (IOException e) {
e.printStackTrace();
throw new ClassNotFoundException(name);
}
}
};
Class clazz = loader.loadClass("classLoaderHotRepresent.Test");
Object account = clazz.newInstance();
account.getClass().getMethod("operation", new Class[]{}).invoke(account);
Thread.sleep(5000);
}
}
}
5.被加载的Test类
public class Test {
public void operation() {
System.out.println("operation version3...");
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6.测试过程
1.先启动Hotload 类,这个类是一个while 循环,每隔五秒钟重新加载一次Test(实际上就是读取Test类编译后的Test.class文件)
2.修改Test中的输出内容,修改好了之后,用idea重新编译一下。更新Test.class文件
3.监测输出结果。