Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 )

2024-03-13 03:48

本文主要是介绍Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 ),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:http://blog.csdn.net/wangxin1982314/article/details/65443335

本文是java热替换的实验,参考了

Java 类的热替换 —— 概念、设计与实现http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html

之前的错误是,没有集成ClassLoader,而是直接使用了
[java]  view plain  copy
  1. classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();  
这个语句只适用于加载.jar
如果加载.class的话需要使用自定义的ClassLoader

[java]  view plain  copy
  1. package yerasel;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileNotFoundException;  
  7. import java.io.IOException;  
  8. import java.io.InputStream;  
  9. import java.io.InputStreamReader;  
  10. import java.lang.reflect.Field;  
  11. import java.lang.reflect.InvocationTargetException;  
  12. import java.lang.reflect.Method;  
  13.   
  14. import java.net.MalformedURLException;  
  15. import java.net.URL;  
  16. import java.net.URLClassLoader;  
  17. import java.util.HashSet;  
  18.   
  19. /* 
  20.  *  实现热部署,自定义ClassLoader,加载的是.class 
  21.  */  
  22. class HowswapCL extends ClassLoader {  
  23.   
  24.     private String basedir; // 需要该类加载器直接加载的类文件的基目录  
  25.     private HashSet dynaclazns; // 需要由该类加载器直接加载的类名  
  26.   
  27.     public HowswapCL(String basedir, String[] clazns) {  
  28.         super(null); // 指定父类加载器为 null  
  29.         this.basedir = basedir;  
  30.         dynaclazns = new HashSet();  
  31.         loadClassByMe(clazns);  
  32.     }  
  33.   
  34.     private void loadClassByMe(String[] clazns) {  
  35.         for (int i = 0; i < clazns.length; i++) {  
  36.             loadDirectly(clazns[i]);  
  37.             dynaclazns.add(clazns[i]);  
  38.         }  
  39.     }  
  40.   
  41.     private Class loadDirectly(String name) {  
  42.         Class cls = null;  
  43.         StringBuffer sb = new StringBuffer(basedir);  
  44.         String classname = name.replace('.', File.separatorChar) + ".class";  
  45.         sb.append(File.separator + classname);  
  46.         File classF = new File(sb.toString());  
  47.         try {  
  48.             cls = instantiateClass(name, new FileInputStream(classF),  
  49.                     classF.length());  
  50.         } catch (FileNotFoundException e) {  
  51.             // TODO Auto-generated catch block  
  52.             e.printStackTrace();  
  53.         }  
  54.         return cls;  
  55.     }  
  56.   
  57.     private Class instantiateClass(String name, InputStream fin, long len) {  
  58.         byte[] raw = new byte[(int) len];  
  59.         try {  
  60.             fin.read(raw);  
  61.             fin.close();  
  62.         } catch (IOException e) {  
  63.             // TODO Auto-generated catch block  
  64.             e.printStackTrace();  
  65.         }  
  66.   
  67.         return defineClass(name, raw, 0, raw.length);  
  68.     }  
  69.   
  70.     protected Class loadClass(String name, boolean resolve)  
  71.             throws ClassNotFoundException {  
  72.         Class cls = null;  
  73.         cls = findLoadedClass(name);  
  74.         if (!this.dynaclazns.contains(name) && cls == null)  
  75.             cls = getSystemClassLoader().loadClass(name);  
  76.         if (cls == null)  
  77.             throw new ClassNotFoundException(name);  
  78.         if (resolve)  
  79.             resolveClass(cls);  
  80.         return cls;  
  81.     }  
  82. }  
  83.   
  84. /* 
  85.  * 每隔500ms运行一次,不断加载class 
  86.  */  
  87. class Multirun implements Runnable {  
  88.     public void run() {  
  89.         try {  
  90.             while (true) {  
  91.                 // 每次都创建出一个新的类加载器  
  92.                 // class需要放在自己package名字的文件夹下  
  93.                 String url = System.getProperty("user.dir") + "/lib";// "/lib/yerasel/GetPI.jar";  
  94.                 HowswapCL cl = new HowswapCL(url,  
  95.                         new String[] { "yerasel.GetPI" });  
  96.                 Class cls = cl.loadClass("yerasel.GetPI");  
  97.                 Object foo = cls.newInstance();  
  98.                 // 被调用函数的参数  
  99.                 Method m = foo.getClass().getMethod("Output"new Class[] {});  
  100.                 m.invoke(foo, new Object[] {});  
  101.                 Thread.sleep(500);  
  102.             }  
  103.   
  104.         } catch (Exception ex) {  
  105.             ex.printStackTrace();  
  106.         }  
  107.     }  
  108. }  
  109.   
  110. public class Test {  
  111.   
  112.     public static Method initAddMethod() {  
  113.         try {  
  114.             Method add = URLClassLoader.class.getDeclaredMethod("addURL",  
  115.                     new Class[] { URL.class });  
  116.             add.setAccessible(true);  
  117.             return add;  
  118.         } catch (Exception e) {  
  119.             throw new RuntimeException(e);  
  120.         }  
  121.     }  
  122.   
  123.     public static void main(String[] args) {  
  124.   
  125.         // 热部署测试代码  
  126.         Thread t;  
  127.         t = new Thread(new Multirun());  
  128.         t.start();  
  129.     }  
  130. }  


GetPI.Java内容:

[java]  view plain  copy
  1. package yerasel;  
  2.   
  3. import java.io.PrintStream;  
  4.   
  5. public class GetPI  
  6. {  
  7.   public static double Darts(int n)  
  8.   {  
  9.     int k = 0;  
  10.     double x = 0.0D;  
  11.     double y = 0.0D;  
  12.     for (int i = 0; i < n; i++)  
  13.     {  
  14.       x = Math.random();  
  15.       y = Math.random();  
  16.   
  17.       if (x * x + y * y <= 1.0D)  
  18.         k++;  
  19.     }  
  20.     return 4 * k / n;  
  21.   }  
  22.   // 本热部署实验中,上面的Darts函数没有用到,请忽略  
  23.   public static void Output() {  
  24.     System.out.println("Output");  
  25.   }  
  26. }  

另一个GetPI.java只在输出时候改为aaaOutput

生成jar包的命令

[java]  view plain  copy
  1. jar cvf GetPI.jar GetPI.class  

一定要注意的是:class需要放在package名字的文件夹下

本文中.class放在/lib(自定义路径)/yerasel(package名字)下。

运行时候,程序加载指定文件夹下的.class,即开始输出aaaOutput,然后手动将另外一个.class(输出Output的.class)覆盖此文件,

程序立即开始输出Output

运行结果图:



这篇关于Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 )的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803551

相关文章

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

基于SpringBoot实现文件秒传功能

《基于SpringBoot实现文件秒传功能》在开发Web应用时,文件上传是一个常见需求,然而,当用户需要上传大文件或相同文件多次时,会造成带宽浪费和服务器存储冗余,此时可以使用文件秒传技术通过识别重复... 目录前言文件秒传原理代码实现1. 创建项目基础结构2. 创建上传存储代码3. 创建Result类4.

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4