Arthas是Alibaba開源的Java診斷工具,功能很強大。官方中文文檔:https://alibaba.github.io/arthas/index.html
本篇主要是介紹 jad / mc / redefine 這三個命令的配合使用,以達到熱更新代碼的目的(命令的詳細使用可參考https://alibaba.github.io/arthas/commands.html)。
1、上傳MathGame.java文件(官網的例子)到linux服務器:
import java.util.concurrent.TimeUnit; /** * 用於Arthas測試jad/mc/redefine命令 */ public class MathGame { public static void main(String[] args) throws InterruptedException { MathGame game = new MathGame(); while (true) { game.run(); TimeUnit.SECONDS.sleep(1); // 這個不生效,因為代碼一直跑在 while里 System.out.println("in loop"); } } public void run() throws InterruptedException { // 這個生效,因為run()函數每次都可以完整結束 System.out.println("call run()"); } }
2、編譯java文件並啟動:
3、使用命令java -jar arthas-boot.jar,啟動Arthas服務:
4、jad命令反編譯MathGame,並將結果輸出到 /tmp/MathGame.java
jad --source-only MathGame > /tmp/MathGame.java
--source-only選項,可以只打印源代碼。
該命令其實很實用,可以查看線上運行的代碼是不是自己想要部署的代碼
5、修改 /tmp的MathGame.java文件,把打印信息加一個"---new"
6、mc內存編譯代碼。將保存好的MathGame.java文件編譯成class文件(也可以在本地使用javac命令編碼):
mc /tmp/MathGame.java -d /tmp
7、redefine重新加載編譯好的.class文件:
redefine /tmp/MathGame.class
可以看到打印結果變了:
redefine的限制:
- 不允許新增field、method
- 正在跑的函數,沒有退出不能生效。比如上面主函數里的System.out.println("in loop"),只有 run 函數里的才會生效
推薦使用 retransform,具體原因可參考:https://arthas.aliyun.com/doc/redefine.html
在使用的過程中發現了一個疑問:當執行完redefine后,最新代碼也生效了,但如果此時再次執行 jad 方法,會發現代碼變成之前的代碼了,並且JVM運行的也是之前的
如果有知道的人,可以在下方評論區回答下,小弟不勝感激~