Java Class的热替换 自定义ClassLoader加载.class
2012-04-09 14:38
537 查看
本文是java热替换的实验,参考了
之前的错误是,没有集成ClassLoader,而是直接使用了
如果加载.class的话需要使用自定义的ClassLoader
GetPI.java内容:
另一个GetPI.java只在输出时候改为aaaOutput
生成jar包的命令
一定要注意的是:class需要放在package名字的文件夹下
本文中.class放在/lib(自定义路径)/yerasel(package名字)下。
运行时候,程序加载指定文件夹下的.class,即开始输出aaaOutput,然后手动将另外一个.class(输出Output的.class)覆盖此文件,
程序立即开始输出Output
运行结果图:
Java 类的热替换 —— 概念、设计与实现http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html
之前的错误是,没有集成ClassLoader,而是直接使用了classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();这个语句只适用于加载.jar
如果加载.class的话需要使用自定义的ClassLoader
package yerasel; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.HashSet; /* * 实现热部署,自定义ClassLoader,加载的是.class */ class HowswapCL extends ClassLoader { private String basedir; // 需要该类加载器直接加载的类文件的基目录 private HashSet dynaclazns; // 需要由该类加载器直接加载的类名 public HowswapCL(String basedir, String[] clazns) { super(null); // 指定父类加载器为 null this.basedir = basedir; dynaclazns = new HashSet(); loadClassByMe(clazns); } private void loadClassByMe(String[] clazns) { for (int i = 0; i < clazns.length; i++) { loadDirectly(clazns[i]); dynaclazns.add(clazns[i]); } } private Class loadDirectly(String name) { Class cls = null; StringBuffer sb = new StringBuffer(basedir); String classname = name.replace('.', File.separatorChar) + ".class"; sb.append(File.separator + classname); File classF = new File(sb.toString()); try { cls = instantiateClass(name, new FileInputStream(classF), classF.length()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return cls; } private Class instantiateClass(String name, InputStream fin, long len) { byte[] raw = new byte[(int) len]; try { fin.read(raw); fin.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return defineClass(name, raw, 0, raw.length); } protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class cls = null; cls = findLoadedClass(name); if (!this.dynaclazns.contains(name) && cls == null) cls = getSystemClassLoader().loadClass(name); if (cls == null) throw new ClassNotFoundException(name); if (resolve) resolveClass(cls); return cls; } } /* * 每隔500ms运行一次,不断加载class */ class Multirun implements Runnable { public void run() { try { while (true) { // 每次都创建出一个新的类加载器 // class需要放在自己package名字的文件夹下 String url = System.getProperty("user.dir") + "/lib";// "/lib/yerasel/GetPI.jar"; HowswapCL cl = new HowswapCL(url, new String[] { "yerasel.GetPI" }); Class cls = cl.loadClass("yerasel.GetPI"); Object foo = cls.newInstance(); // 被调用函数的参数 Method m = foo.getClass().getMethod("Output", new Class[] {}); m.invoke(foo, new Object[] {}); Thread.sleep(500); } } catch (Exception ex) { ex.printStackTrace(); } } } public class Test { public static Method initAddMethod() { try { Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class }); add.setAccessible(true); return add; } catch (Exception e) { throw new RuntimeException(e); } } public static void main(String[] args) { // 热部署测试代码 Thread t; t = new Thread(new Multirun()); t.start(); } }
GetPI.java内容:
package yerasel; import java.io.PrintStream; public class GetPI { public static double Darts(int n) { int k = 0; double x = 0.0D; double y = 0.0D; for (int i = 0; i < n; i++) { x = Math.random(); y = Math.random(); if (x * x + y * y <= 1.0D) k++; } return 4 * k / n; } // 本热部署实验中,上面的Darts函数没有用到,请忽略 public static void Output() { System.out.println("Output"); } }
另一个GetPI.java只在输出时候改为aaaOutput
生成jar包的命令
jar cvf GetPI.jar GetPI.class
一定要注意的是:class需要放在package名字的文件夹下
本文中.class放在/lib(自定义路径)/yerasel(package名字)下。
运行时候,程序加载指定文件夹下的.class,即开始输出aaaOutput,然后手动将另外一个.class(输出Output的.class)覆盖此文件,
程序立即开始输出Output
运行结果图:
相关文章推荐
- Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 )
- Java Class的热替换 自定义ClassLoader加载.class
- Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 )
- 类的加载器 java.lang.ClassLoader
- Java ClassLoader基础及加载不同依赖 Jar 中的公共类
- 类加载过程以及ClassLoader特性和热替换
- Java Class的热替换 自定义ClassLoader加载.class
- Java ClassLoader加载.jar
- java中的类加载器(原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/)
- Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)
- Java 自定义ClassLoader
- 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码
- Java ClassLoader加载.jar
- Java 类加载体系与ContextClassLoader
- 浅析java中ClassLoader如何加载Class
- Java ClassLoader基础及加载不同依赖 Jar 中的公共类
- 图解classloader加载class的流程及自定义ClassLoader
- 已经加载了类库,还是报错启动报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderList
- Java中各类ClassLoader加载时资源搜索路径
- Java ClassLoader 类加载 与 SOA后期优化