本文目录导读:

我将为您提供一个完整的Java热加载案例,包括核心实现和示例代码。
自定义类加载器实现
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义类加载器,支持热加载
*/
public class HotSwapClassLoader extends ClassLoader {
// 监控的class文件目录
private String classPath;
// 存储类的加载时间戳
private Map<String, Long> classModifiedTimeMap = new HashMap<>();
// 存储已加载的类
private Map<String, Class<?>> loadedClasses = new HashMap<>();
public HotSwapClassLoader(String classPath) {
this.classPath = classPath;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
// 优先加载自定义类
if (name.startsWith("com.example.hotswap")) {
return findClass(name);
}
// 其他类交给父类加载器
return super.loadClass(name);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String fileName = name.replace('.', File.separatorChar) + ".class";
String filePath = classPath + File.separator + fileName;
File classFile = new File(filePath);
if (!classFile.exists()) {
throw new ClassNotFoundException(name);
}
try {
byte[] classBytes = loadClassBytes(filePath);
Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length);
loadedClasses.put(name, clazz);
return clazz;
} catch (Exception e) {
throw new ClassNotFoundException("Failed to load class: " + name, e);
}
}
private byte[] loadClassBytes(String filePath) throws IOException {
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file)) {
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
return bytes;
}
}
/**
* 检查类是否有更新
*/
public boolean isClassModified(String className) {
String fileName = className.replace('.', File.separatorChar) + ".class";
String filePath = classPath + File.separator + fileName;
File classFile = new File(filePath);
if (!classFile.exists()) {
return false;
}
long lastModified = classFile.lastModified();
Long previousTime = classModifiedTimeMap.get(className);
if (previousTime == null) {
classModifiedTimeMap.put(className, lastModified);
return true;
}
if (previousTime != lastModified) {
classModifiedTimeMap.put(className, lastModified);
return true;
}
return false;
}
public Map<String, Class<?>> getLoadedClasses() {
return loadedClasses;
}
}
热加载管理器
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 热加载管理器
*/
public class HotSwapManager {
private static volatile HotSwapManager instance;
// 类加载器
private volatile HotSwapClassLoader classLoader;
// 配置信息
private HotSwapConfig config;
// 已加载的服务实例
private ConcurrentHashMap<String, Object> serviceInstances = new ConcurrentHashMap<>();
// 定时检查服务
private ScheduledExecutorService scheduler;
private HotSwapManager(HotSwapConfig config) {
this.config = config;
this.classLoader = new HotSwapClassLoader(config.getClassPath());
startMonitor();
}
public static HotSwapManager getInstance(HotSwapConfig config) {
if (instance == null) {
synchronized (HotSwapManager.class) {
if (instance == null) {
instance = new HotSwapManager(config);
}
}
}
return instance;
}
/**
* 获取服务实例,支持热加载
*/
public <T> T getService(Class<T> interfaceClass) {
String className = interfaceClass.getName();
// 检查是否需要重新加载
if (classLoader.isClassModified(className)) {
reloadClass(className);
}
// 获取或创建实例
Object instance = serviceInstances.get(className);
if (instance == null) {
instance = createInstance(className);
if (instance != null) {
serviceInstances.put(className, instance);
}
}
return interfaceClass.cast(instance);
}
/**
* 获取服务实例(通过实际类名)
*/
public Object getService(String className) {
// 检查是否需要重新加载
if (classLoader.isClassModified(className)) {
reloadClass(className);
}
Object instance = serviceInstances.get(className);
if (instance == null) {
instance = createInstance(className);
if (instance != null) {
serviceInstances.put(className, instance);
}
}
return instance;
}
/**
* 重新加载类
*/
private void reloadClass(String className) {
try {
// 创建新的类加载器
HotSwapClassLoader newLoader = new HotSwapClassLoader(config.getClassPath());
// 设置父加载器
newLoader.setParent(classLoader);
// 加载类
Class<?> clazz = newLoader.loadClass(className);
// 创建新实例
Object newInstance = clazz.newInstance();
// 更新实例和加载器
serviceInstances.put(className, newInstance);
classLoader = newLoader;
System.out.println("[" + System.currentTimeMillis() + "] 热加载成功: " + className);
} catch (Exception e) {
System.err.println("热加载失败: " + className);
e.printStackTrace();
}
}
/**
* 创建实例
*/
private Object createInstance(String className) {
try {
Class<?> clazz = classLoader.loadClass(className);
return clazz.newInstance();
} catch (Exception e) {
System.err.println("创建实例失败: " + className);
e.printStackTrace();
return null;
}
}
/**
* 启动监控线程
*/
private void startMonitor() {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
checkAndReload();
}, 0, config.getCheckInterval(), TimeUnit.MILLISECONDS);
}
/**
* 检查并重新加载所有已加载的类
*/
private void checkAndReload() {
for (String className : serviceInstances.keySet()) {
if (classLoader.isClassModified(className)) {
reloadClass(className);
}
}
}
/**
* 停止监控
*/
public void shutdown() {
if (scheduler != null) {
scheduler.shutdown();
}
}
public static class HotSwapConfig {
private String classPath; // 类文件路径
private long checkInterval = 3000; // 检查间隔(毫秒)
public HotSwapConfig(String classPath) {
this.classPath = classPath;
}
public String getClassPath() {
return classPath;
}
public long getCheckInterval() {
return checkInterval;
}
public HotSwapConfig setCheckInterval(long checkInterval) {
this.checkInterval = checkInterval;
return this;
}
}
}
接口定义和实现类
package com.example.hotswap;
/**
* 服务接口
*/
public interface GreetingService {
String greet(String name);
}
package com.example.hotswap;
/**
* 服务实现类 - 可热更新的实现
*/
public class GreetingServiceImpl implements GreetingService {
private String version = "v1.0";
@Override
public String greet(String name) {
return "版本 " + version + ": Hello, " + name + "! 当前时间: " + new java.util.Date();
}
}
测试示例
import com.example.hotswap.GreetingService;
import com.example.hotswap.GreetingServiceImpl;
/**
* 热加载测试类
*/
public class HotSwapExample {
public static void main(String[] args) throws Exception {
// 配置类路径
String classPath = "/path/to/your/classes";
// 创建配置
HotSwapManager.HotSwapConfig config = new HotSwapManager.HotSwapConfig(classPath)
.setCheckInterval(2000); // 2秒检查一次
// 获取实例
HotSwapManager manager = HotSwapManager.getInstance(config);
// 获取服务(通过接口)
GreetingService service = manager.getService(GreetingService.class);
System.out.println(service.greet("Alice"));
// 模拟运行中
for (int i = 0; i < 10; i++) {
Thread.sleep(3000);
// 重新获取服务,检查是否有更新
service = manager.getService(GreetingService.class);
System.out.println("检查 " + (i+1) + ": " + service.greet("Bob"));
}
// 停止监控
manager.shutdown();
}
}
热更新工具类
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLClassLoader;
/**
* 动态编译测试工具类
*/
public class HotSwapTestUtil {
/**
* 编译Java源码文件
*/
public static boolean compileJavaFile(String sourceFile, String outputDir) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
File dir = new File(outputDir);
if (!dir.exists()) {
dir.mkdirs();
}
int result = compiler.run(null, null, null,
"-d", outputDir, sourceFile);
return result == 0;
}
/**
* 动态生成修改后的类
*/
public static void updateClassFile() throws Exception {
String sourcePath = "/path/to/source/GreetingServiceImpl.java";
String outputDir = "/path/to/classes";
// 修改源码(这里简化处理,实际应用中可能需要动态生成)
String source = "package com.example.hotswap;\n" +
"public class GreetingServiceImpl implements GreetingService {\n" +
" private String version = \"v2.0\";\n" +
" public String greet(String name) {\n" +
" return \"版本 \" + version + \": Hello, \" + name + \"! (Updated)\";\n" +
" }\n" +
"}\n";
// 写源文件
File sourceFile = new File(sourcePath);
try (FileOutputStream fos = new FileOutputStream(sourceFile)) {
fos.write(source.getBytes());
}
// 编译
boolean success = compileJavaFile(sourcePath, outputDir);
if (success) {
System.out.println("类文件更新成功!");
}
}
}
使用说明
-
目录结构:
classes/ com/ example/ hotswap/ GreetingService.class GreetingServiceImpl.class -
测试步骤:
- 运行主程序,会加载初始版本
- 修改
GreetingServiceImpl.java中的version字段 - 重新编译该文件到classes目录
- 程序会检测到文件变化并自动加载新版本
-
核心特性:
- 支持定期检查类文件变化
- 自动重新加载修改的类
- 保持已有的服务实例
- 通过接口实现解耦
这个案例展示了如何实现Java类的热加载,适用于需要动态更新功能的场景,如插件系统、规则引擎等。