伯樂線上注:本文來自文章作者張開濤的推薦投稿(原文)。如果其他朋友也有不錯的原創或譯文,可以嘗試推薦給伯樂線上。
————————————————————
上一篇Spring/Hibernate提升速度的文章《加速spring/hibernate應用除錯時啟動速度》,主要是通過一些技巧來提升啟動速度,還是做不到如類的熱部署/熱替換。因此再寫一篇關於熱部署/熱替換的文章。之前也有很多人介紹過這些知識,不過比較分散,我寫此篇的目的是聚合它們。本文以 HotSpot 虛擬機器為例。
首先讓我們來看兩個概念:熱部署、熱替換
熱部署
即在容器執行過程中,重新載入類或重新載入整個專案。常見的解決方案就是使用自定義ClassLoader;
部分載入的示例:如JSP、Play框架;
重新載入整個專案的示例:如Tomcat、Jetty;預設都是定期檢測class檔案是否有修改,如果有,先解除安裝當前容器,再重新載入整個專案(reload)。
這種情況缺點很明顯:只能重新裝載整個類/整個專案,不能只替換類中的部分。
JSP熱部署的介紹:
http://www.linuxidc.com/Linux/2013-05/83816.htm
Tomcat熱部署的介紹:
http://www.94it.cn/a/jingxuanboke/2013/0501/4578.html
Play!框架:
http://mingj.iteye.com/blog/307238
熱替換
熱替換相對於之前的熱部署的優勢就是可以替換如方法體、增刪方法/欄位等類內部區域性替換,而不是整個類。常見的實現方式:HotSpot虛擬機器的HotSwap、HotSwap補丁、
HotSwap
只能熱替換方法體。只要在eclipse或idea等開發工具中開啟debug模式即可使用。
HotSwap補丁 DCEVM
該補丁增強了HotSwap,可以增加、刪除類欄位、方法和改變類的父類。也必須在debug模式下除錯。具體使用可以參考如下文章,在此就不重複了
我測試時使用的是jdk1.6.0_25,沒有問題,不支援jdk1.6.0_26,且我測試jdk7_13和jdk7_21沒成功。官網介紹說其是基於JDK7-b102編譯的。估計我下的這兩個版本不對。
java agent + Instrumentation
1、Spring-Loaded
SpringSource官網釋出的,用在Grails 2中,允許:新增/修改/刪除 方法/欄位/構造器。型別/方法/欄位/構造器上的註解也允許修改,且也可以新增/刪除/修改enum型別的值。
使用方式:
1 |
-javaagent:<pathTo>/springloaded-{VERSION}.jar -noverify |
如在執行tomcat/jetty時的VM引數中指定如上配置即可。無需在debug模式下執行。如果使用的是如idea可以按Ctrl+Shift+F9編譯當前類/Ctrl+F9編譯所有更改的類。
2、Fakereplace
類似於Spring-Loaded,具體可參考其官網:
https://github.com/fakereplace/fakereplace
https://github.com/fakereplace/fakereplace/wiki/How-It-Works
它的好處是,支援一些框架:
- Seam 2
- Weld (基本整合)
- JSF
- Metawidget
- Hibernate (實際是如果實體修改了,重啟整個EMF,也不是很快)
- Resteasy
具體使用也是在VM引數中指定:
1 |
-javaagent:/path/to/fakereplace.jar |
可以到如下地址下載jar包,或自己編譯
http://repo.grails.org/grails/plugins-releases/org/fakereplace/fakereplace-dist/1.0.0.Alpha2/
其提供了一些配置,如:
1 |
-javaagent:/path/to/fakereplace.jar=packages=com.mycompany.myclasses,log=trace |
- packages 需要熱替換的包
- log 可選,支援trace,debug,info,error
- index-file fakereplace索引為的路徑。Fakereplace在第一次執行後儲存這個檔案以加速啟動
- dump-dir 當熱替換時,Dump類到這個目錄,僅當開發Fakereplace時有用
- port Fakereplace監聽的埠
它倆的實現很類似,Spring-Loaded使用了CGLIB來實現代理,FakeReplace使用了Javassist來實現的。
還有如Agent Smith,不過N久沒維護了。 其實Play框架也是使用了Instrumentation,但是它是整個替換,所以沒有歸類過來。
以上的都有個缺點:如我在寫spring專案時,無法動態載入如@RequestMapping配置,或動態載入配置檔案。這些在強大的JRebel中都是支援的。
JRebel
JRebel是我目前簡單的最強大的熱替換/熱部署工具。但缺點是收費的,而且不便宜。之前介紹的都是免費的。首先大家可以看一下它支援的特性與JVM Hot Swap對比列表:
JavaEE支援 | JRebel | JVM Hot Swap |
裝載時間 | <1s | <1s |
記憶體洩漏 | 無 | 無 |
改變類結構 | ||
改變方法體 | ||
新增/刪除方法 | ||
新增/刪除構造器 | ||
新增/刪除欄位 | ||
新增/刪除類 | ||
新增/刪除註解 | ||
改變靜態欄位值 | ||
新增/刪除enum值 | ||
改變介面 | ||
替換父類 | ||
新增/刪除實現的介面 | ||
即時構建 | ||
跳過WAR目錄的構建 | ||
跳過.WAR/.EAR類更新構建 | ||
跳過.WAR/.EAR資源更新構建 | ||
對映多個source目錄到一個.WAR/.EAR目標目錄 | ||
使用include/exclude模式對映類和資源 | ||
使用Ant風格模式對映多個sourcde目錄 | ||
使用系統屬性使對映機器無關 | ||
Maven外掛 | ||
遠端/雲 | ||
通過HTTP進行應用更新 |
JavaEE支援
JSP EL changes |
JSP Scriptlet changes |
EJB 1.x session bean interface changes |
EJB 2.x session bean interface changes |
EJB 3.x session bean interface changes |
EJB 3.x: adding new EJB |
EJB 3.x: adding new EJB reference |
JSF changes (Mojarra) |
Bean Validation support (Hibernate Validator) |
JAXB annotation changes |
JAX-RS changes (RESTEasy, Jersey, CXF) |
JAX-WS support (Metro, CXF) |
JPA changes (Hibernate, EclipseLink, TopLink, OpenJPA) |
CDI changes (Weld) |
框架支援 |
Spring Framework 2.x or later |
Hibernate |
JBoss Seam 2.x or later |
Google Guice |
Struts 1.x, 2.x |
Wicket |
Stripes 1.5 or later |
檢視完整的框架支援列表 |
代理支援 |
CgLib |
Javassist |
OSGi支援 |
Apache Felix |
Eclipse Equinox |
從如上列表看到其不是一般的強大。
接下來看看如何使用(以IDEA為例):
1、首先點選如下圖所示的執行,然後點選Edit Configuration…
2、在彈出的視窗中輸入如下圖所示的jrebel.jar位置
類似於之前的javaagent配置。
3、啟動後,當修改類後,請按Ctrl+F9重新編譯。然後再執行程式即可看到變化。
4、Eclipse內嵌tomcat的配置:
使用起來是非常簡單的。注意:如果使用web容器如tomcat、jetty,請禁用其reload,如jetty,可以配置
<scanIntervalSeconds>0</scanIntervalSeconds> 或者 <reload>manual</reload>。
JRebel也提供如Eclipse、IDEA、Maven外掛,其實沒必要上外掛,直接配javaagent就很簡單。還可以配置
如果有朋友想開啟/禁用某些框架/JavaEE的支援,可以通過新增VM引數,如下所示開啟/關閉:
-Drebel.spring_plugin=true
-Drebel.aspectj_plugin=true
-Drebel.struts2_plugin=true
-Drebel.hibernate_plugin=true
-Drebel.jackson_plugin=true
-Drebel.log4j-plugin=true
還可以通過配置一個rebel.xml來進行選擇性構建:
http://zeroturnaround.com/software/jrebel/how-to-configure-rebel-xml/
更多配置請參考其官方的JRebel手冊。
到此就介紹完了我見到的所有熱部署/熱替換實現方式,大家還有什麼好的方式歡迎補充。
參考資源: