hotswapagent——热更新代码而无需重启生产环境

原创 2016年06月12日 15:37:43

coding阶段,我们习惯于以debug模式运行程序,享受即时更新代码而无需重启服务的高效开发速度。

遗憾的是,无论是ide的debug模式,还是jdk1.4+的instrument机制,都只能做到修改方法体的热更新。如果你添加或删除了某些method或field,马上就会报热更失败的提示。

那么有没有什么高大上的工具能够支持动态修改类结构呢?答案是肯定的。

JRebel——一个jvm插件,允许开发者随时修改代码、资源而无需重启服务。在eclipse商店里就有一个JRebel的插件。但JRebel是收费软件,当然,网上也有破解版。

本文将介绍另外一个免费工具——HotswapAgent+DCEVM组合。

The Dynamic Code Evolution Virtual Machine (DCEVM) 是一个jvm级别的补丁,安装过程会替换jvm自身的文件。DCEVM的官网最后一次更新是为了兼容jdk1.7,对于最新的jdk1.8则无能为力。

HotswapAgent是一个git开源项目,github地址-->HotswapAgent。项目上最新的DCEVM是支持jdk1.8的。

在官网上下载DCEVM-light.jarhotswap-agent.jar 两个jar包并安装DCEVM后,就可以开始我们的探索之旅了。

1.编写实体类

public class Person  {

	public String toString(){
		return "from person,hello";
	}
}

2.编写测试入口

public class Entry {

     public static void main(String[] args) throws Exception {
		final Person p = new Person();  //内存只有一个实例对象
		new Thread(
				new Runnable(){
					@Override
					public void run() {
						while(true){
							try{
								Thread.sleep(1000);
								System.err.println(p);
							}catch(Exception e){

							}
						}
					}
				}
				).start();

	}
}

3.以Eclipse开发工具为例,配置vm参数,然后以debug模式启动程序

vm参数(-XXaltjvm=dcevm -javaagent:E:\workspace\jar_libs\hotswap-agent.jar),如下所示

启动后,看到终端输出如下提示,就说明环境配置成功


4.程序启动后,修改实体类并保存代码(ide要开启自动编译)

public class Person  {

	private final int age = 3; 	  //动态加字段,这里要加final修饰
	public String toString(){
		testAddMethod();
		return "from person,hello,age="+age; //动态修改方法体
	}
	
	public void testAddMethod(){  //动态加方法
		System.err.println("hot update ,add method succ.......");
	}
	
}
5.运行结果如下,可以看到,热更成功了!!!!!!

6.虽然以debug模式热更新成功,但在生产环境一般都不是debug模式,那么在生产环境应如果部署呢?

其实也是相当简单,只需要稍微修改一下vm参数,命令行执行参数为

java -XXaltjvm=dcevm -javaagent:E:\workspace\jar_libs\hotswap-agent.jar=autoHotswap=true Entry

在运行过程中,使用已编译后的新class文件去替换旧class文件,即可看到热更效果。

7.若项目是以可执行jar包的方式部署,只需在编译后的class根目录里面新建一个文件hotswap-agent.properties,然后设置extraClasspath为指定的更新路径,同时设置autoHotswap=true,将需要更新的文件放到extraClasspath目录下,即可更新指定文件。

8.最后说一下使用hotswapagent的一些限制。

官网上说Hotswap除了无法修改类的层次关系(例如改变父类或移除接口),其他热更操作均可实现。但从我个人的测试方法来看,官网的说法还是有些夸大成分。如果真的是要在生产环境上使用此方法进行热部署,强烈推荐一定要先在本地环境试验一番,确保有效才能放到生产环境。

自己随便测试了一番,发现以下操作无法热更成功,也有可能是我使用方法有误(^_^)

1.增加实例属性并赋值,打印后发现赋值无效,输出的是类型的默认值,使用final常量则能生效。应该是由于实例初始化过程已经结束,不再走实例的属性初始化逻辑。

2.修改匿名类方法体里用到的实例引用,程序直接宕机停止运行抓狂发火,示例代码如下


报错异常为

<span style="font-family:SimHei;">HOTSWAP AGENT: 15:19:8.283 RELOAD (org.hotswap.agent.config.PluginManager) - Reloading classes [Entry, Entry$1] (autoHotswap)
HOTSWAP AGENT: 15:19:8.316 RELOAD (org.hotswap.agent.plugin.jvm.AnonymousClassPatchPlugin) - Class '/Entry' has been enhanced with anonymous classes for hotswap.
Exception in thread "Thread-3" java.lang.NoSuchFieldError: val$p
	at .Entry$1.run(Entry.java:18)
	at java.lang.Thread.run(Thread.java:745)</span>

使用反编译工具查看匿名类的代码发现,报错的引用"val$p"指向的是原匿名类的引用,报错原因暂不详害羞

估计是因为匿名类的缘故。匿名类,内部类一直是热更的软肋。我所接触的热更方式都要求代码尽量不要出现内部类,匿名类。



总结:

hotswapagent给我们的开发过程带来了无与伦比的快感,想象一下,在开发运行过程就可以随意增减方法,随时随地进行代码重构,这该有多爽啊。但由于该工具仍处于alpha版本,稳定性无法考量,我曾发邮件咨询过作者,作者也建议不要轻易放到生产环境!!Anyway,在生产环境能够修改方法体,已足矣。。。

版权声明:本文为博主原创文章,未经博主允许不得转载。

如何用HotSwapAgent和DCEVM让java开发像js开发一样高效(JRebel的替代方案)

要高效的开发Java代码,那就必须要让java像js一样,修改过的代码可以实时的反应出来。要了解如何做到这一点,我们先要知道JVM是如何工作的: 我们知道,JAVA程序都是运行在java虚拟机上...
  • u013613428
  • u013613428
  • 2016年05月25日 17:41
  • 10036

JVM之-----热部署hotswap

热部署是在不重启 Java 虚拟机的前提下,能自动侦测到 class 文件的变化,更新运行时 class 的行为。       目前的 Java 虚拟机只能实现方法体的修改热部署,对于整个类的结构修...
  • nameix
  • nameix
  • 2016年08月22日 16:41
  • 2361

Groovy脚本热更新

背景: Java应用定时调用脚本,采集系统监控信息。调用方式1:边解释边执行  如下图所示,当监听到脚本变化后,只需要在内存中更新脚本内容即可,下次执行eval时就能执行最新的脚本了。 调用方式2:...
  • yangguosb
  • yangguosb
  • 2017年10月30日 17:29
  • 170

groovy与java集成的坑

背景groovy用来和java集成,作为动态规则引擎使用,是非常不错的一个选择。简单来说,就是用java来执行一段groovy代码。可以通过一个简单的数据库配置,来动态的执行某段脚本。这样就可以实时得...
  • jianghuihong2012
  • jianghuihong2012
  • 2017年05月07日 21:45
  • 1240

【转】精通IntelliJ Idea之热部署

原文:http://blog.buyihanshe.com/20090606/mastering-intellij-idea-hot-deploy.htm 部署在项目开发过程中是常有的事,特别是de...
  • wag2765
  • wag2765
  • 2016年01月25日 16:27
  • 5395

java热加载技术hotswap

关于hotswap 是一个允许在运行状态下无限制的修改加载类文件的Java虚拟机补丁。当前java虚拟机的动态加载机制只允许修改类的方法体,而打了hotswap补丁以后,可以增加,删除类属性,方法,甚...
  • flysharkym
  • flysharkym
  • 2016年04月03日 13:19
  • 1295

手游服务端框架之网关

网关介绍游戏服务器的网关,主要是用于手机客户端与游戏业务服务端通信的中转器,负责接收来自手机客户端的请求协议,以及推送服务端的响应包。在单一进程服务端架构里,网关跟游戏业务处理是在同一个进程里。为了提...
  • littleschemer
  • littleschemer
  • 2017年06月24日 14:17
  • 2284

Java服务器热部署的实现原理

今天发现早年在大象笔记中写的一篇笔记,之前放在ijavaboy上的,现在它已经访问不了了。前几天又有同事在讨论这个问题。这里拿来分享一下。 在web应用开发或者游戏服务器开发的过程中,我们时...
  • chenjie19891104
  • chenjie19891104
  • 2015年01月17日 19:12
  • 36058

Java游戏服务器代码热更新

一般碰到这个问题首先想到的解决方案都是考虑new 一个classLoader来加载新的类,这样的解决方式有什么优点和缺点呢。 使用ClassLoader的方式加载类就涉及到一些需要知道的知识点。双亲委...
  • huaye2007
  • huaye2007
  • 2017年04月25日 09:09
  • 2598

Java服务器热部署的实现原理——java类的加载方式

在web应用开发或者游戏服务器开发的过程中,我们时时刻刻都在使用热部署。热部署的目的很简单,就是为了节省应用开发和发布的时间。比如,我们在使用Tomcat或者Jboss等应用服务器开发应用时,我们经常...
  • xiaopihai86
  • xiaopihai86
  • 2016年02月29日 19:25
  • 3447
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hotswapagent——热更新代码而无需重启生产环境
举报原因:
原因补充:

(最多只允许输入30个字)