本文是java热替换的实验,参考了 Java 类的热替换 —— 概念、设计与实现 http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html。 之前的错误是,没有集成ClassLoader,而是直接使用了

[java] view plaincopy
  1. classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();

这个语句只适用于加载.jar

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

GetPI.Java内容:

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

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

生成jar包的命令

[java] view plaincopy
  1. jar cvf GetPI.jar GetPI.class

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

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

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

程序立即开始输出Output

运行结果图:

Java Class的热替换 自定义ClassLoader加载.class相关推荐

  1. java自定义classloader_java自定义ClassLoader加载指定的class文件操作

    继承ClassLoader并且重写findClass方法就可以自定义一个类加载器,具体什么是类加载器以及类加载器的加载过程与顺序下次再说,下面给出一个小demo 首先定义一个类,比如MyTest,并且 ...

  2. java的classloader_java自定义ClassLoader加载指定的class文件操作

    继承ClassLoader并且重写findClass方法就可以自定义一个类加载器,具体什么是类加载器以及类加载器的加载过程与顺序下次再说,下面给出一个小demo 首先定义一个类,比如MyTest,并且 ...

  3. Java 类的热替换---转载

    构建基于 Java 的在线升级系统 Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础 ...

  4. Java 类的热替换 —— 概念、设计与实现

    Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础概念.关于 ClassLoader ...

  5. Java的ClassLoader加载是怎么保证安全的?

    点击上方蓝色字体,选择"标星公众号" 优质文章,第一时间送达 1.类加载机制 Java中的源码.java后缀文件会在运行前被编译成.class后缀文件,文件内的字节码的本质就是一个 ...

  6. 图解classloader加载class的流程及自定义ClassLoader

    http://longdick.iteye.com/blog/442213 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有B ...

  7. java类加载器顺序_java中类的加载顺序介绍(ClassLoader)

    1.ClassNotFoundExcetpion 我们在开发中,经常可以遇见java.lang.ClassNotFoundExcetpion这个异常,今天我就来总结一下这个问题.对于这个异常,它实质涉 ...

  8. java 类加载生命周期_Java类的加载与生命周期

    一.概要: 类的生命周期从类的 加载.连接.初始化 开始,到类的 卸载结束: 二.几个阶段: 加载:查找并加载类的二进制数据.(把类的.class文件的二进制数据读入内存,存放在运行时数据区的方法区: ...

  9. java类 连接时机_java类的加载时机

    类加载 它直接表现出来的代码应该是 ClassLoader.getSystemClassLoader().loadClass("com.my.test.AbcClass").所以具 ...

最新文章

  1. R语言ggplot2可视化:ggplot2可视化散点图并使用geom_mark_circle函数在数据簇或数据分组的数据点周围添加圆圈进行注释(自定义圆圈的大小)
  2. modernizr 支持html5,使用modernizr.js检测浏览器对html5以及css3的支持情况
  3. 3org.springframework.beans.factory.BeanDefinitionStoreException异常
  4. 初始化字典的6种方式
  5. Windows下安装Python模块时环境配置
  6. 树莓派4b装系统_树莓派4B初次使用--系统安装|配置
  7. jQuery EasyUI API 中文文档 - 数据表格(DataGrid)
  8. python涉及excel_Python实现EXCEL的常规操作,一文涵盖10个方面
  9. ubuntu linux u盘安装教程,U盘安装ubuntu的详细教程
  10. taro Button按钮组件
  11. 黑眼圈大神程序员用5000字带你通透读懂Elasticsearch的注意事项
  12. IDrawingDoc Interface 学习笔记
  13. 冬瓜哥送你元宵大礼盒啦!!
  14. 瀚高数据库适配定时框架Quartz
  15. 【NLP】⚠️学不会打我! 半小时学会基本操作 8⚠️ 新闻分类
  16. 懒人理财法之基金定投(Automatic Investment Plan)
  17. umi+@umijs/plugin-qiankun的应用
  18. ECharts如何制作省份地图并在地图上显示自定义图标/散点图
  19. CTFshow--RSA
  20. 一个三流学校程序员的奋斗

热门文章

  1. thymeleaf 的 th:onclick js方法入参
  2. metasploit 使用search报错
  3. 【专栏必读】王道考研408数据结构万字笔记(有了它不需要你再做笔记了):各章节内容概述导航和思维导图
  4. 栈溢出笔记1.8 字符串问题
  5. LeetCode 81 搜索旋转排序数组 II
  6. Python 包含\u字符串转中文(\u00)
  7. Linux无线网卡的工作模式
  8. Oracle bug 使用max或min函数into到一个char类型报字符缓冲区太小的错误
  9. 黑马程序员_java基础笔记(06)...集合
  10. 洛谷P2312解方程题解