在运行时通过热插拔机制更改方法

2022-08-31 16:29:01

假设我们有一个简单的Java程序,它只包含一个类:

public class HelloWorld {

   private static void replacable(int i) {
      System.out.println("Today is a nice day with a number " + i);
   }        

   public static void main(String[] args) throws Exception {
      for(int i = 0; i < 100000; ++i) {
      replacable(i);
      Thread.sleep(500);
   }
}

编译并运行后,输出将是这样的:

今天是数字0的好日子

今天是一个美好的一天,有一个数字1

今天是一个美好的一天,有一个数字2

今天是一个美好的一天,有一个数字3

...

我的问题是:是否存在(或者即将出现)某种在运行时交换方法的方法?就像用新版本编写另一个版本一样,编译它,然后在已经运行的JVM中编写旧版本?replacableHelloWorldreplacable

所以,如果我这样写新版本:

private static void replacable(int i) {
   System.out.println("Today is an even nicer day with a number " + i);
}  

有没有类似于Erlang的热代码交换的东西,我可以这样做:

  1. 运行原始程序
  2. 写入修改版本
  3. 使用命令行程序,连接到正在运行的JVM并替换现有方法

因此,在运行时,这将发生:

今天是一个美好的一天,数字为15000

今天是一个美好的一天,编号为15001

今天是一个更好的日子,数字15002

今天是一个更好的日子,编号为15003

...

假设上述程序是独立的,在标准的Java SE环境中运行,classpath上没有其他内容,因此它几乎是Hello world风格的程序。

注意:我知道像字节码操作(cglib),aspectJjRebelJMX,Java EE中的方法热交换等技术存在,但它们不是我想到的。想想二郎。


答案 1

您可以使用开源的 HotSpot VM 或商用 JRebel IDE 插件来轻松实现您的目标(在此处查看比较表)。


答案 2

您可以通过类装入器执行此操作。例如,如果您熟悉 Servlet 容器(如 tomcat),它会在开发中修改页面时重新加载页面。这是在java中创建动态代码的一个很好的解释。它不仅解释了加载,还解释了动态编译源代码。您应该能够将所涵盖的概念应用于要使用的重新加载代码的任何策略。


推荐