假设我们有一个简单的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号...
我的问题:是否存在(或者是否存在)某种方式在运行时交换 replacable
方法?有点像用新版本的 replacable
编写另一个版本的 HelloWorld
,在已经运行的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的东西,我可以这样做:
-
运行原始程序
-
写了修改版
-
使用命令行程序,连接到正在运行的JVM并替换现有方法
这样,在运行时,这将发生:
今天是一个美好的一天,数字15000今天是一个美好的一天,数字15001今天是一个更好的一天,数字15002今天是一个更好的一天,数字15003 ...
假设上面的程序是独立的,在标准的Java SE环境中运行,类路径上没有别的东西,所以它几乎是一个Hello世界风格的程序 .
注意:我知道存在像字节码操作(cglib),aspectJ,jRebel,JMX,Java EE等方法的热交换等技术,但它们并没有想到 . 想想二郎 .
7 回答
您可以使用开源HotSpot VM或商业JRebel IDE插件轻松实现目标(查看比较表here) .
我在很多项目中都使用了这个hotswap ant task . 目标java应用程序可以通过Ant,Eclipse,命令提示符或任何其他方式启动,只要它在调试模式下启动并打开相应的端口即可 . 链接页面提供了有关如何通过Ant执行此操作的说明 .
只要更改不是结构化的,任何数量的类都可以被热交换 . 方法体的变化通常很容易热交换 . 可以通过shell或Eclipse运行ant脚本来解密代码 .
在工作中,我利用一个脚本,通过比较类文件的时间戳来自动热交换代码更改 . 这类似于项目页面上的示例,该示例显示了一个只有hotswaps更改类的简单示例 .
附加说明:这使用JPDA .
OSGi怎么样?热交换有点“内置”到规范 - 我认为这也是一种可能的解决方案 .
您可以通过JPDA(Java平台调试器体系结构)界面执行此操作:http://download.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap
它不是自动的Erlang案例 - JVM不会监视类路径更改类文件然后重新加载并重新链接它们(如果更改),原因相当明显(Java是为Web部署而设计的,您不想轮询用于更改的http URL) .
您可以使用策略设计模式,因此您有一个操作对象而不是方法,以及与程序通信的协议,以告诉它使用给定的类名作为Strategy对象的类 .
你可以通过类加载器来完成 . 例如,如果您熟悉诸如tomcat之类的Servlet容器,那么在开发过程中修改它们时会重新加载页面 . 这是great explanation of creating dynamic code in java . 它不仅可以解释加载,还可以动态编译源代码 . 您应该能够将所涵盖的概念应用于任何重新加载要使用的代码的策略 .
一个稍微过时的帖子,但希望有人会觉得这很有用:
我发现相对较新的Hotswap Agent有很好的文档和功能丰富(最重要的是,open source) .