Java实现热加载的三种方式

您所在的位置:网站首页 java自定义类加载器热更 Java实现热加载的三种方式

Java实现热加载的三种方式

2023-09-10 21:27| 来源: 网络整理| 查看: 265

基于java agent方式

新建一个maven工程

public static void premain(String agentArgs, Instrumentation inst) { Trace.info("HotAgent-premain-start"); Trace.info("isReadefineClassesSupported:" +inst.isRedefineClassesSupported()); new Reloader(inst).reload(); } public static void agentmain(String agentArgs, Instrumentation inst) { premain(agentArgs, inst); }

再pom中增加一下

org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 UTF-8 org.apache.maven.plugins maven-jar-plugin 3.0.2 true com.reload.HotAgent com.reload.HotAgent

核心代码如下 主要是利用JDK中Instrument的redefine方法去重定义class,去重新加载了Class.

for (ClassDefinitionWrap rWrap : redefineClassWrap) { Trace.info("redefine class" + rWrap.getClassname()); inst.redefineClasses(new ClassDefinition(rWrap.getCls(), rWrap.getBs())); result.appendMsg("热加载类:ࣺ"+rWrap.getClassname()+"成功"); } 基于Classloader方式

热加载就是利用新建自定义Classloader去加载Class,让后利用Thread的contexClassloader去替换老的classloader加载的class,这样就能实现 热加载。以下是demo的代码:

TestClassLoader testClassLoader = new TestClassLoader(); System.out.println("parent classloader:" + testClassLoader.getParent()); Thread.currentThread().setContextClassLoader(testClassLoader); Class clazz = testClassLoader.loadClass("com.plugin.AutoReload"); System.out.println(clazz.hashCode()); System.out.println(clazz.getClassLoader()); System.out.println(testClassLoader); TestClassLoader newClassLoader = new TestClassLoader(Thread.currentThread().getContextClassLoader()); Thread.currentThread().setContextClassLoader(newClassLoader); System.out.println(newClassLoader); Class clazz1 = newClassLoader.loadClass("com.plugin.AutoReload"); System.out.println(clazz1.hashCode()); System.out.println(clazz1.getClassLoader());

自定义Classloader的示例代码:

public class TestClassLoader extends ClassLoader { public TestClassLoader(ClassLoader parent) { super(parent); } public TestClassLoader(){ } @Override public Class loadClass(String name) throws ClassNotFoundException { Class c = null; synchronized (getClassLoadingLock(name)) { if (c == null) { try { ClassLoader parent = getParent(); if (parent != null) { c = parent.loadClass(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } } if (c != null) { return c; } byte[] bytes = loadclassData(name); System.out.println("=====" + name); if(bytes != null) { return defineClass(name, bytes, 0, bytes.length); } } throw new ClassNotFoundException(name); } private byte[] loadclassData(String className) { return getContent(getResourceStream(className)); } private InputStream getResourceStream(String toLoadClassName) { System.out.println("load class name " + toLoadClassName); try { JarFile jar = new JarFile(Constants.WATCH_PACKAGE + File.separator + "plugin-1.0-SNAPSHOT.jar"); // 包名 Enumeration entry = jar.entries(); JarEntry jarEntry; String name; String className; Class clazz = null; while (entry.hasMoreElements()) { jarEntry = entry.nextElement(); name = jarEntry.getName(); if (name.startsWith("/")) { name = name.substring(1); } if (jarEntry.isDirectory() || !name.endsWith(".class")) { continue; } // 去掉 .class className = name.substring(0, name.length() - 6).replace("/", "."); System.out.println(className); if (className.equals(toLoadClassName)) { return jar.getInputStream(jarEntry); } } } catch (IOException e) { e.printStackTrace(); } return null; } public byte[] getContent(InputStream inputStream) { // 读取Class文件呢 ByteArrayOutputStream byteSt = new ByteArrayOutputStream(); // 写入byteStream int len = 0; try (InputStream in = inputStream) { while ((len = in.read()) != -1) { byteSt.write(len); } } catch ( IOException e) { e.printStackTrace(); } // 转换为数组 return byteSt.toByteArray(); } } 基于groovy方式

基于Groovy方式,就是利用GroovyClassLoader的重新加载脚本,重新生成一个Class,GroovyClassLoader每次调用parseClass都是新城一个新的Class,这样就能实现Class的热加载.

String scriptContent = "package com.reload\n" + "\n" + "import org.springframework.beans.factory.annotation.Autowired\n" + "\n" + "class Hello {\n" + "\n" + " @Autowired\n" + " HelloService service;\n" + "\n" + " HelloService getService() {\n" + " return service\n" + " }\n" + "\n" + " def run() {\n" + " print(service.hello())\n" + " }\n" + "}"; GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); Class clazz = null; for (int i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3