最近在研究java的熱更新,花了些時間精力在網上找了些資料,發現好多資料講的不清不楚(可能是自己技術菜看不懂),沒有一篇講的比較詳細的博客,有的還缺省了一些步驟,這還不要緊,要命的是按照他的步驟做了最後沒成功還費了半天的無用功你說氣不氣人。所以今天寫下自己在弄的時候遇到的一些坑順便給填了。
首先單獨開一個工程,裏邊就寫一個包含agentmain方法的類比如我的JavaAgent類
下面是這個工程得到截圖
之後再maven的pom文件中設置MANIFEST.MF的Agent-Class值,這個值就是指向上邊創建的JavaAgent類路勁
<build>
<finalName>xxx</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Agent-Class>
org.yztun.JavaAgent
</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
上截圖
這個只要在pom文件中指定就行,maven打包的時候自己會生成MANIFEST.MF文件並自己設置Agent-Class的值,比如我打包之後的xxx.jar結構是這樣的
那麼這個工程一打包就完事了
再梳理下上面的步驟
1)創建一個maven工程就命名爲yztun吧
2)在yztun工程中創建一個帶有agentmain方法的類比如我的JavaAgent類。
3)在pom文件中設置MANIFEST.MF的Agent-Class的值比如我這裏JavaAgent的org.yztun.JavaAgent
4)打包,這個不用說了吧,找到maven的install雙擊等待運行完成就行
接下啦再創建一個啓動工程
public class A66 {
public static void main(String[] args) throws Exception {
List<VirtualMachineDescriptor> list = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : list) {
if (vmd.displayName().endsWith("Main")) {
VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());
virtualMachine.loadAgent("D:/JavaWork/hot-fix/xxx/target/xxx.jar ", "cxs");
System.out.println("ok");
virtualMachine.detach();
}
}
}
}
這裏的virtualMachine.loadAgent("D:/JavaWork/hot-fix/xxx/target/xxx.jar ", "cxs");其中"D:/JavaWork/hot-fix/xxx/target/xxx.jar "是yztun工程打包之後的羣路徑那個jar包名是xxx.jar。if (vmd.displayName().endsWith("Main"))就是查找你要熱更新那個工程的住函數類名了。等會會講到,
上截圖
這段代碼跟第一個工程的代碼一樣重要,這裏是告訴虛擬機你要熱更新的那個工程的主入口,等會我們斷點看看這個list會有什麼東西而VirtualMachineDescriptor這個類需要你引入你安裝jdk下的tools包否則找不到這個類
這個自己到自己電腦的jdk安裝目錄去找然後導入就行,至於路勁這個看你把jdk安裝到哪個路徑咯。
,好了。到這裏其實熱更新用到代碼都寫完了,很少。接下來就說說怎麼用吧。
我這裏是又創建了一個工程來測試的,其執行代碼的主類,就相當於要熱更新的工程
Test測試類
接下來運行測試工程,有於測試工程有個死循環所以沒隔一秒會調用一次Test.test();
這樣當我們的Test.test();內容有變動是就會熱更新成功
沒熱更之前的輸出
接下來我們直接在不停止測試工程的情況下修改Test.test();然後編譯生成新的class文件然後運行A66的main方法就可熱更新成功
再來看輸出