天天看點

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

要高效的開發Java代碼,那就必須要讓java像js一樣,修改過的代碼可以實時的反應出來。要了解如何做到這一點,我們先要知道JVM是如何工作的:

我們知道,JAVA程式都是運作在java虛拟機上面(當然JVM有兩種類型,JDK和單純的JRE,這裡我們主要是指的JDK,因為隻有JDK包含了debug功能,而我們隻有在debug端口打開的情況下才能實作run time class load),我們的寫的每一個Java檔案,會被編譯器編譯成為class檔案,然後根據選擇不同的打包選擇,比如說(jar, war, ear),被打包存放到系統的classpath中。在運作一個java程式的時候,會有幾個步驟, 包括裝載,連結,初始化,翻譯(在翻譯成機器碼的時候同時會對代碼進行優化,inline),運作,就如下圖

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

這裡的關鍵,就是這個classloader。所有的類都會在jvm中生成為class對象,存放在記憶體當中,(這裡,主要分成兩部分,常量池和方法位元組碼)當我們的程式生成一個類的執行個體或instance時候,就會根據這個類對象,配置設定和初始化記憶體用于存儲對象的field,然後在調用對象方法的時候,則從class對象中擷取方法位元組碼,如下圖:

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

是以,如果我們能夠在JVM裡面途歡這個class對象,那麼我們建立的所有object或instance,在調用函數的時候,就可以動态獲得你修改之後的代碼。如下圖:

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

hotswap的原理,就是替換jvm裡面的class對象. Sun 在2002年把這項技術引入到java 1.4的JVM中,Hotswap需要和debuggerAPI一起協同工作,我們可以通過debugger來更新jvm裡面同名的class bytecode

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

是以,這也就限制了,我們在使用hotswap的時候,必須使用debug mode.是以也就限制了java app必須是運作在jdk上,而不是jre上,JAVA_HOME必須指向JDK。

說了這麼多理論,回到我們最初的話題,如何做到hotswap呢,步驟很簡單:

  1. 用debug模式attach我們的app
  2. 修改你的java檔案,并且編譯
  3. 這時,神奇的事情發生了,如下圖
如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

我們的class被reload了,我們可以不用重新把app部署到伺服器上就可以直接看修改代碼之後的結果。

等等,天底下有這麼容易的事情嗎?!這個solution是有缺陷的,那就是我們隻能簡單修改class method的内容,如果我們新添加了Method,field,或者在method裡面引用了新的lib,增加了Import語句,那麼對不起,你會看到:

如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)

hot swap失敗了。

那麼有沒有什麼解決方案呢?有!收費的JRebel,或者免費的HotSwapAgent+DCEVM

讓我們來看看什麼是DCEVM:

https://dcevm.github.io / The Dynamic Code Evolution VirtualMachine (DCEVM)is a modification of the Java HotSpot(TM) VM that allows unlimited redefinitionof loaded classes at runtime. The current hotswapping mechanism of the HotSpot(TM) VM allows only changing methodbodies. Our enhanced VMallows adding and removing fields and methods as well as changes to the supertypes of a class. 什麼是hotswapAgent:

uhttp://www.hotswapagent.org/ uHotswap agent does the work of reloadingresources and framework configuration (Spring, Hibernate, ...) uHotswapagentis a plugin container with plugin manager, plugin registry, and several agentservices (e.g. to watch for class/resource change). It helps with common tasksand classloading issues. It scans classpath for class annotated with @Pluginannotation, injects agent services and registers reloading hooks. Runtimebytecode modification is provided by javaasist library.

具體怎麼用?

  1. 照着我上頭給的兩個位址安裝他們,具體怎麼搞,我比較懶,就不寫了(注意,在安裝DCEVM的時候,請用臨時替換)"InstallDCEVM as altjvm" 
  2. 如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)
  3. 配置你的運作腳本(假設你的APP是運作在各種伺服器上,比如tomcat, jboss等),上頭兩個網站也有,别告訴我你看不懂英文,我還是懶,不想寫
  4. 運作的程式,檢查hotswapAgent有沒有起來,有沒有使用DCEVM(注意下圖的 -XXaltjvm=dcevm)
  5. 如何用HotSwapAgent和DCEVM讓java開發像js開發一樣高效(JRebel的替代方案)
  6. 然後,随意修改的java代碼,享受編譯之後直接替換的樂趣吧