Java热加载

什么是热加载

热加载是指可以在不重启服务的情况下让更改的代码生效,热加载可以显著的提升开发以及调试的效率,它是基于 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。执行结果如下

相关阅读

Java的热部署和热加载

Java服务器热部署的实现原理

深入探索 Java 热部署

Groovy实现代码热载的机制和原理

 

 


版权声明:本文为LittleSkey原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。