背景
儘管在生產環境熱更新程式碼,並不是很好的行為,很可能導致:熱更不規範,同事兩行淚。
但很多時候我們的確希望能熱更新程式碼,比如:
線上排查問題,找到修復思路了,但應用重啟之後,環境現場就變了,難以復現。怎麼驗證修復方案?
又比如:
本地開發時,發現某個開源元件有bug,希望修改驗證。如果是自己編譯開源元件再發布,流程非常的長,還不一定能編譯成功。有沒有辦法快速測試?
Arthas是阿里巴巴開源的Java應用診斷利器,深受開發者喜愛。
下面介紹利用Arthas 3.1.0版本的 jad
/mc
/redefine
一條龍來熱更新程式碼。
- Arthas: github.com/alibaba/art…
- jad命令:alibaba.github.io/arthas/jad.…
- mc命令:alibaba.github.io/arthas/mc.h…
- redefine命令:alibaba.github.io/arthas/rede…
Arthas線上教程
下面通過Arthas線上教程演示熱更新程式碼的過程。
在例子裡,訪問 curl http://localhost/user/0
,會返回500錯誤:
{
"timestamp": 1550223186170,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.IllegalArgumentException",
"message": "id < 1",
"path": "/user/0"
}
複製程式碼
下面通過熱更新程式碼,修改這個邏輯。
jad反編譯程式碼
反編譯UserController
,儲存到 /tmp/UserController.java
檔案裡。
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
複製程式碼
修改反編繹出來的程式碼
用文字編輯器修改/tmp/UserController.java
,把丟擲異常改為正常返回:
@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {
logger.info("id: {}", (Object)id);
if (id != null && id < 1) {
return new User(id, "name" + id);
// throw new IllegalArgumentException("id < 1");
}
return new User(id.intValue(), "name" + id);
}
複製程式碼
sc查詢載入UserController的ClassLoader
$ sc -d *UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
複製程式碼
可以發現是spring boot的 LaunchedURLClassLoader@1be6f5c3
載入的。
mc記憶體編繹程式碼
儲存好/tmp/UserController.java
之後,使用mc(Memory Compiler)命令來編譯,並且通過-c
引數指定ClassLoader
:
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms
複製程式碼
redefine熱更新程式碼
再使用redefine命令重新載入新編譯好的UserController.class
:
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1
複製程式碼
檢驗熱更新結果
再次訪問 curl http://localhost/user/0
,會正常返回:
{
"id": 0,
"name": "name0"
}
複製程式碼
總結
Arthas裡 jad
/mc
/redefine
一條龍來線上熱更新程式碼,非常強大,但也很危險,需要做好許可權管理。
比如,線上應用啟動帳號是 admin,當使用者可以切換到admin,那麼
- 使用者可以修改,獲取到應用的任意記憶體值(不管是否java應用)
- 使用者可以attach jvm
- attach jvm之後,利用jvm本身的api可以redefine class
所以:
- 應用的安全主要靠使用者許可權本身的管理
- Arthas主要是讓jvm redefine更容易了。使用者也可以利用其它工具達到同樣的效果
最後,Arthas提醒您: 診斷千萬條,規範第一條,熱更不規範,同事兩行淚。
Arthas實踐系列
- Alibaba Arthas實踐--獲取到Spring Context,然後為所欲為
- Arthas實踐--快速排查Spring Boot應用404/401問題
- 當Dubbo遇上Arthas:排查問題的實踐
- Arthas實踐--使用redefine排查應用奇怪的日誌來源
- 使用Arthas抽絲剝繭排查線上應用日誌打滿問題
- 深入Spring Boot:利用Arthas排查NoSuchMethodError
公眾號
歡迎關注橫雲斷嶺的專欄,專注Java,Spring Boot,Arthas,Dubbo。