如何为Eclipse上的Tomcat配置代码热替换(Hot Code Replacement )

本博客会引导你配置Eclipse的Tomcat的热代码替换(也叫作hotswap debugging)java

  • 什么是“热代码替换”
  • 什么是“JPDA”、“JDI”
  • 基于JPDA的Tomcat的配置
  • “JPDA”的局限性——Catch
  • 改进方案1:DCEVM
  • 改进方案2:JRebel

什么是“热代码替换”

“热代码替换”(Hot Code Replace,如下简称HCR)就是当你正在调试web程序的时候,jvm容许让你修改的Java代码马上生效,而不用重启程序,HCR是Java Platform Debugger Architecture(JPDA)的一部分(它包含不少东西,好比咱们的远程调试也是),HCR在现代JVM中都有支持。git

看下以下的代码:github

public class Sample {
  public static void main(String[] args) {
    String foo = "unchangeable";
    foo += blah();
    System.out.println(foo);
  }
  
  public static String blah() {
    String bar = "bar";
    bar += "blah";
    return bar;
  }
  
}

若是你正在Eclipse中调试这段代码,你能够修改它,在线的,而不用重启程序,好比,在blah方法的第二行打一个断点,而后调试程序,程序会在bar +=那行挂起,而后修改把字符串“blah”改成“quz”,保存文件,程序会继续运行,当前行会跳到blah方法的第一行,而且会以新的代码运行。web

什么是“JPDA”、“JDI”

简单来讲,Java Platform Debugger Architecture(JPDA)就是Java提供的一套用于开发Java调试工具的规范,任何的JDK实现都须要实现这个规范。数据库

JDI是这套调试工具提供的API接口,JDI的API在com.sun.jdi包下,至关因而JDI的接口规范了。除了JDK自带的实现外,我在HotSpot的SA中也发现了一个实现。他俩的实现分别是在com.sun.tools.jdi包下和sun.jvm.hotspot.jdi包下浏览器

正是由于有了他们,你才能够像上面那么玩儿。缓存

“JPDA”的局限性——catch

你在基于Tomcat运行的web程序中也能够这么玩儿,可是会有一些问题:tomcat

“Hot Code Replace Failed”app

Some code changes cannot be hot swapped into a running virtual machine, such as changing method names or introducing errors into running code. The current target virtual machine was unable to replace It is safe to continue ...框架

而后给你4个按钮:continue、details、terminate、restart

这个提示应该很眼熟吧,这个叫作Catch。而后刚刚修改的代码也没有生效,连行号都不对了。

什么是Catch?

当咱们在使用HCR的时候仍是有不少限制的:

  1. HCR只能替换方法里面的代码
  2. 不能修改类签名(类名、继承类、实现接口)、方法签名(方法名和参数列表)、成员变量
  3. 不能新增类
  4. 特殊的方法调用不能修改,例如main方法,经过反射调用的方法(这些统称为“stack frames”)

若是你修改了,那么上面的错误提示就出来了。

基于Tomcat的Web项目配置

配置基于Tomcat的web项目

项目配置,咱们一般能够按照以下的步骤将web项目部署到Eclipse的Tomcat中:

  1. 下载EE版的Eclipse
  2. 在设置中配置Tomcat。打开设置,找到Servers,而后
  3. 建立Dynamic Web Project
  4. 在Servers视图中new Server
  5. 右击建立好的Tomcat,选择Add And Remove...,将项目部署到Tomcat中
  6. 以Debug模式启动Tomcat

禁用Auto Reloading

发布到Tomcat中的项目,默认都是开启Auto Reloading的,为了更好地使用JPDA功能,请按照以下步骤禁用Tomcat的Auto Reloading

  1. 双击Servers View中的Tomcat。
  2. Services View应该是默认就有的,万一没有或者被关闭了,你能够经过以下方式打开它:菜单:window→show view→services。
  3. 切换到Modules,选中要修改的project,而后点击edit,去掉“Auto Reloading Enabled”前面的勾。

为何禁用Auto Reloading

Auto Reloading是一种tomcat用来实现不使用JPDA状况下支持java类热替换的。在这种模式下,Tomcat使用java中的classloaders来卸载并从新加载class,当它从新加的时候,tomcat会尝试从新初始化你的系统,从新启动那些在web.xml中标记为load-on-startup的servlet。

结果是,当你的项目里面有不少的启动代码时,这么作并不会给你节省时间,例如:若是你的启动代码须要初始化Hibernate的数据库缓存,Spring的依赖注入配置等等,你将会花费更长的时间,甚至比重启tomcat还要长。

更加坑爹的是,被自动加载的程序有时候会变得很奇怪,并且很是容易出现PermGen的内存溢出,这些都是由于频繁的卸载、从新加载类引发的。当出现这个错误的时候,重启tomcat一般能够解决这个问题。若是你即便只花费了5分钟来解决从新加载的问题,你也被坑了,由于原本你期望经过reload来作到比重启tomcat更省时间的,结果并无。

经过禁用这个“Auto Reloading”来改成使用JPDA的代码热替换,你得到了更为可靠的代码热替换。

禁用“Auto Reloading”可是启用“Auto Publishing”

根据上面说的,你应该知道如何禁用“Auto Reloading”了吧,虽然“Auto Reloading”会致使JPDA工做不正常,可是tomcat的配置页的“Overview”Tab页有另外一个设置叫作“Automatically publish when resources change”,它默认是手气的,你能够点击按钮展开它;当你禁用了“Auto Reloading”之后,这个“Auto Publishing”请确保已经打开。

为了了解二者的区别,咱们须要先了解一下Eclipse的WTP是如何工做的。当你在Eclipse了里面建立了一个“Server”之后,Eclipse会在你的workspace中建立一个虚拟的Tomcat目录,这个目录里面完整包含了:conf、logs、temp、webapps、works这些目录,当你配置了这个服务,其实你就告诉了Eclipse去哪儿找tomcat的运行目录,但并不会使用webapps目录里面任何你的配置文件或者数据,在Eclipse启动tomcat的时候,它将虚拟目录的位置经过启动启动参数的方式传递给了jvm。

“发布(Publishing)”意思就是说将你所有的代码复制到这个虚拟目录中,包括:JSP、jar包,配置文件,动态生成的配置等等。

若是你禁用了这个发布功能,那么你就须要右击Server View里面你的Tomcat,而后点击“Publish”菜单了,并且每次你保存代码都要这么来一遍,更加好的是,若是你开启了“Auto Publishing”,Tomcat能够自动就支持JSP的自动从新加载(能够不用JPDA就能够支持)。

找到Tomcat虚拟目录tmp0

不少时候,看下tomcat虚拟目录的里面都有什么东西对咱们代码开发是很是有帮助的。经过以下方式咱们能够找到tomcat虚拟目录:经过双击Servers View中的Tomcat,在弹出的页面中找到Service Locations,咱们就能够看到了,一般,虚拟目录在:.metadata/.plugins/org.eclipse.wst.server.core/tmp0,最后一个0是会变的,多个Tomcat的时候会从0开始往上涨。

这个.metadata目录在你的workspace中(你能够经过以下方式找到workspace的位置:菜单:FileSwitch Workspace默认的那个就是你当前的workspace),或者,启动Eclipse的时候让你选择的workspace就是你当前的workspace。

在这个虚拟目录中,你能够看到全部Eclipse自动建立的目录,看看conf目录下的server.xml,检查一下work目录下jsp自动生成的java文件,webapps里面确定是空的,由于Eclipse使用的是wtpwebapps目录。

改进方案:

上面说了,JPDA有不少的局限性,可是国外牛人的能力是强大的,咱们能够经过以下的方式来让咱们的代码开发更加高效!

DCEVM

这个是github上的一个开源项目,是国外的一个牛人基于OpenJDK7的源码从新编写了其中代码热替换部分实现的jvm,经过将咱们默认的Hotspot JVM替换为此JVM,就能够自动实现类名修改、方法名修改等一些JPDA不支持的代码热替换了。

JRebel

JavaRebel 是一个代码热替换系统,它要比HCR好一点 (可能好不少),也能弥补DCEVM对不少web框架不支持的不足。

有了JavaRebel,你能够在不重启Tomcat地状况下增长、删除方法和类,并且多个project同时运行时不会串,更好的是,它支持对不少框架都加入了支持(Spring、Struts、Jboss等等),好比,你正在基于Spring作代码开发,新增了一个Controller类或者增长了一个方法(有@RequestMapping),一般状况下,你须要重启Tomcat来让其生效,可是若是你的Eclipse安装了JavaRebel,那么当你保存的时候,Controller的信息就所有从新加载了,直接在浏览器就能够访问对应的URL!

惟一的缺憾就是,它收费,每一个开发人员每一年须要支付149美圆,固然了,在天朝,嘿嘿(*^__^*) 。

相关文章
相关标签/搜索