什么是热加载
热加载是指可以在不重启服务的情况下让更改的代码生效,热加载可以显著的提升开发以及调试的效率,它是基于 Java 的类加载器实现的,但是由于热加载的不安全性,一般不会用于正式的生产环境。
热加载和热部署的区别
首先,不管是热加载还是热部署,都可以在不重启服务的情况下编译/部署项目,都是基于 Java 的类加载器实现的。那么两者到底有什么区别呢?
- 热部署是在服务器运行时重新部署项目。
- 热加载是在运行时重新加载 class。
热加载实现思路
根据Java的类加载机制,我们可操作的环节只有加载阶段。同时为了避免双亲委派机制的限制,热加载类对系统加载类是不可见的(它加载过了,就变更不了啦),要通过其他加载类加载(如URLClassLoader、自定义加载器等)。
例子
热加载的接口
package com.sky.learn.hotload;
/**
* 要热加载的类一定要有一个接口或基类引用
* @author Administrator
*/
public interface HotLoadInf {
public void show();
}
测试类
package com.sky.learn.hotload;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;
/**
* 测试热加载客户端类
*
* @author Administrator
*
*/
public class Client {
private static ClassLoader classLoader;
private static Class<?> hotLoadClass;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
HotLoadInf instance= createInstance();
System.out.println("OPT: show, reload, or exit");
while (true) {
// 根据不同的协议命令执行不同的逻辑,利用热加载,我们可以在修改具体的逻辑代码之后不重启服务器实现热加载
String cmd = br.readLine();
if (cmd.equalsIgnoreCase("exit")) {
return;
} else if (cmd.equalsIgnoreCase("reload")) {
reloadImpl();
instance= createInstance();
System.out.println("HotLoadImpl reloaded.");
} else if (cmd.equalsIgnoreCase("show")) {
instance.show();
}
}
}
/**
* 使用加载的类 hotLoadClass 类创建 HotLoadImpl 实例
*/
public static synchronized HotLoadInf createInstance() throws Exception {
if (hotLoadClass == null) {
reloadImpl();
}
HotLoadInf newInstance = (HotLoadInf) hotLoadClass.newInstance();
return newInstance;
}
/**
* 用类加载器重新加载 HotLoadImpl
*/
public static synchronized void reloadImpl() throws Exception {
URL[] externalURLs = new URL[] { new URL("file:F://") };
classLoader = new URLClassLoader(externalURLs);
hotLoadClass = classLoader.loadClass("com.sky.learn.hotload.HotLoadImpl");
}
}
创建两个实现类
package com.sky.learn.hotload;
public class HotLoadImpl implements HotLoadInf {
public void show() {
System.out.println("I'm HotLoad Test1!");
}
}
package com.sky.learn.hotload;
public class HotLoadImpl implements HotLoadInf {
public void show() {
System.out.println("I'm HotLoad Test2!");
}
}
将实现类生成的两个.class文件复制到F盘(代码中文件路径)包路径后,删除HotLoadImpl文件。否则会加载应用中该类。
执行main方法,reload前修改要加载的class文件名为HotLoadImpl.class。执行结果如下
相关阅读