Arthas神器實戰
- Arthas
-
- 0引言
- 1安裝
- 2常用指令
- 3熱部署Java類
Arthas
0引言
當你遇到以下問題而束手無策時,Arthas或許可以幫助你:
- 這個類從哪個jar包加載的?為什麼會報各種類相關的Exception?
- 我改的代碼為何沒有執行?難道我沒有commit?版本不對?替換JAR再重新開機?
- 遇到問題無法線上上debug,難道隻能通過加日志再重新釋出嗎?
- 線上遇到某個使用者的資料處理有問題,但線上同樣無法debug,而線下複現成本巨大,頭疼?
- 是否有一個全局的視圖來檢視系統運作狀況?
- 有什麼辦法可以監控到JVM的實時運作狀态?
- 如何快速定位應用的熱點,生成火焰圖?
1安裝

根據推薦,使用如下指令啟動Arthas,
java -jar arthas-boot.jar
java -jar arthas-boot.jar ${pid}
針對docker容器内的安裝,需要傳入Arthas壓縮包![]()
Arthas神器實戰Arthas ![]()
Arthas神器實戰Arthas
sudo docker cp /home/sunquan-temp/arthas-packaging-3.2.0-bin.zip ff32:/home
gunzip -d arthas-packaging-3.2.0-bin.zip
2常用指令
-
dashboard
針對程序目前内部情況的資訊概覽,其中包括線程、記憶體、運作時常量,如圖:
Arthas神器實戰Arthas
3熱部署Java類
本節是介紹複用Arthas如何在不重新開機的情況下修改源碼并使其生效。以一個spring-boot項目為例。
@Api(tags = "使用者子產品")
@Controller
public class UserController {
@ApiOperation(value = "使用者登入", notes = "随邊說點啥")
@ApiImplicitParams({
@ApiImplicitParam(name = "mobile", value = "手機号", required = true, paramType = "query"),
@ApiImplicitParam(name = "password", value = "密碼", required = true, paramType = "query"),
//針對int類型要固定定義example
@ApiImplicitParam(name = "age", value = "年齡", required = true, paramType = "query", example = "1", defaultValue = "1", dataType = "int")
})
@ApiResponses({
@ApiResponse(code = 200, message = "請求成功"),
@ApiResponse(code = 400, message = "請求參數沒填好"),
@ApiResponse(code = 404, message = "請求路徑沒有或頁面跳轉路徑不對")
})
@ResponseBody
@PostMapping("/login")
public UserLoginVO login(@RequestParam String mobile, @RequestParam String password,
@RequestParam int age) {
System.out.println(mobile + password + age);
UserLoginVO userLoginVO = new UserLoginVO();
userLoginVO.setPassword(password);
userLoginVO.setUsername(mobile);
//System.out.println("success");
return userLoginVO;
}
}
通過請求最終傳回:
{
“username”: “18912345675”,
“password”: “bca”
}
此時需要在該方法中顯示列印一條success,在不重新開機服務情況下,通過Arthas步驟如下:
1、修改源碼,增加success列印,如果你已經有源碼,則可以在已有的源碼上修改,如果沒有,需要通過jad命名反編譯位元組碼為源碼,如
jad --source-only com.zte.sunquan.spring.ReadingListController > F:/1/ReadingListController.java
通過上述指令可以得到源碼
2、通過sc查詢該代碼在目前程序中的類加載器對象執行個體
sc -d com.zte.sunquan.spring.ReadingListController | grep classLoaderHash
3、使用mc反編譯修改後的類檔案
mc -c 2513c0f4 E:/01sq-code/demo-for-learing-sq/spring-demo/src/main/java/com/zte/sunquan/spring/UserController.java -d F:/1
ps.該指令中直接使用IDE中的類檔案,且在指定目錄生成位元組碼檔案
4、使用redefine指令重新加載編碼好的新位元組碼檔案
redefine F:/1/com/zte/sunquan/spring/UserController.class
ps.注意修改的JAVA類,不允許新增field/method,以及正在跑的函數,也不能有内部類,如未退出則不生效
結果:
再試觸發rest調用,發現控制台果然列印出了success