通过热交换机制在运行时更改方法

时间:2010-12-29 10:38:01

标签: java runtime hotswap

假设我们有一个简单的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

     

今天是一个很好的一天,有一个数字

     

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

     

今天是一个美好的一天,有一个3号

     

...

我的问题:在运行时交换replacable方法的某种方式是否存在(或者是否存在)?有点像用HelloWorld的新版本编写replacable的另一个版本,编译它,然后在已经运行的JVM中编译旧版本?

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

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

有类似Erlang's hot code swapping的内容,我可以这样做:

  1. 运行原创程序
  2. 编写修改后的版本
  3. 使用命令行程序,连接到正在运行的JVM并替换现有方法
  4. 这样,在运行时,会发生这种情况:

      

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

         

    今天是一个美好的一天,数量为15001

         

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

         

    今天是一个更好的日子,数量为15003

         

    ...

    假设上面的程序是独立的,在标准的Java SE环境中运行,类路径上没有别的东西,所以它几乎是一个Hello世界风格的程序。

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

7 个答案:

答案 0 :(得分:38)

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

答案 1 :(得分:15)

您可以通过类加载器来完成。例如,如果您熟悉诸如tomcat之类的Servlet容器,那么在开发过程中修改它们时会重新加载页面。这是一个great explanation of creating dynamic code in java。它不仅可以解释加载,还可以动态编译源代码。您应该能够将所涵盖的概念应用于任何重新加载要使用的代码的策略。

答案 2 :(得分:9)

我在很多项目中使用了这个hotswap ant task。目标java应用程序可以通过Ant,Eclipse,命令提示符或任何其他方式启动,只要它在调试模式下启动并打开相应的端口即可。链接页面提供了有关如何通过Ant执行此操作的说明。

只要更改不是结构化的,任何数量的类都可以被热交换。方法体的变化通常很容易变热。可以通过shell或Eclipse运行ant脚本来彻底破坏代码。

在工作中,我利用一个脚本,通过比较类文件的时间戳来自动热交换代码更改。这类似于项目页面上的示例,该示例显示了一个只有hotswaps更改类的简单示例。

附加说明:这会使用JPDA

答案 3 :(得分:3)

稍微过时的帖子,但希望有人会觉得这很有用:

我发现相对较新的Hotswap Agent有详细记录且功能丰富(最重要的是,open source)。

答案 4 :(得分:2)

您可以通过JPDA(Java平台调试器架构)界面执行此操作:http://download.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap

它不是自动的Erlang案例 - JVM不会监视类路径更改类文件然后重新加载并重新链接它们(如果更改),原因相当明显(Java是为Web部署而设计的,你不想这样做正在轮询http URL以进行更改。)

答案 5 :(得分:1)

OSGi怎么样?热交换有点“内置”到规范中 - 我认为这也是一种可能的解决方案。

答案 6 :(得分:1)

您可以使用策略设计模式,因此您有一个操作对象而不是方法,以及与程序通信的协议,以告诉它使用给定的类名作为Strategy对象的类。 / p>