Java实现热加载案例

wen java案例 1

本文目录导读:

Java实现热加载案例

  1. 自定义类加载器实现
  2. 热加载管理器
  3. 接口定义和实现类
  4. 测试示例
  5. 热更新工具类
  6. 使用说明

我将为您提供一个完整的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("类文件更新成功!");
        }
    }
}

使用说明

  1. 目录结构

    classes/
    com/
     example/
       hotswap/
         GreetingService.class
         GreetingServiceImpl.class
  2. 测试步骤

    • 运行主程序,会加载初始版本
    • 修改GreetingServiceImpl.java中的version字段
    • 重新编译该文件到classes目录
    • 程序会检测到文件变化并自动加载新版本
  3. 核心特性

    • 支持定期检查类文件变化
    • 自动重新加载修改的类
    • 保持已有的服务实例
    • 通过接口实现解耦

这个案例展示了如何实现Java类的热加载,适用于需要动态更新功能的场景,如插件系统、规则引擎等。

抱歉,评论功能暂时关闭!