本博客会引导你配置Eclipse的Tomcat的热代码替换(也叫作hotswap debugging)java
“热代码替换”(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
简单来讲,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包下浏览器
正是由于有了他们,你才能够像上面那么玩儿。缓存
你在基于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。而后刚刚修改的代码也没有生效,连行号都不对了。
当咱们在使用HCR的时候仍是有不少限制的:
若是你修改了,那么上面的错误提示就出来了。
项目配置,咱们一般能够按照以下的步骤将web项目部署到Eclipse的Tomcat中:
发布到Tomcat中的项目,默认都是开启Auto Reloading的,为了更好地使用JPDA功能,请按照以下步骤禁用Tomcat的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 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虚拟目录的里面都有什么东西对咱们代码开发是很是有帮助的。经过以下方式咱们能够找到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有不少的局限性,可是国外牛人的能力是强大的,咱们能够经过以下的方式来让咱们的代码开发更加高效!
这个是github上的一个开源项目,是国外的一个牛人基于OpenJDK7的源码从新编写了其中代码热替换部分实现的jvm,经过将咱们默认的Hotspot JVM替换为此JVM,就能够自动实现类名修改、方法名修改等一些JPDA不支持的代码热替换了。
JavaRebel 是一个代码热替换系统,它要比HCR好一点 (可能好不少),也能弥补DCEVM对不少web框架不支持的不足。
有了JavaRebel,你能够在不重启Tomcat地状况下增长、删除方法和类,并且多个project同时运行时不会串,更好的是,它支持对不少框架都加入了支持(Spring、Struts、Jboss等等),好比,你正在基于Spring作代码开发,新增了一个Controller类或者增长了一个方法(有@RequestMapping),一般状况下,你须要重启Tomcat来让其生效,可是若是你的Eclipse安装了JavaRebel,那么当你保存的时候,Controller的信息就所有从新加载了,直接在浏览器就能够访问对应的URL!
惟一的缺憾就是,它收费,每一个开发人员每一年须要支付149美圆,固然了,在天朝,嘿嘿(*^__^*) 。