盡管在生產(chǎn)環(huán)境熱更新代碼,并不是很好的行為,很可能導(dǎo)致:熱更不規(guī)范,同事兩行淚。
但很多時(shí)候我們的確希望能熱更新代碼,比如:
線上排查問(wèn)題,找到修復(fù)思路了,但應(yīng)用重啟之后,環(huán)境現(xiàn)場(chǎng)就變了,難以復(fù)現(xiàn)。怎么驗(yàn)證修復(fù)方案?
又比如:
本地開(kāi)發(fā)時(shí),發(fā)現(xiàn)某個(gè)開(kāi)源組件有bug,希望修改驗(yàn)證。如果是自己編譯開(kāi)源組件再發(fā)布,流程非常的長(zhǎng),還不一定能編譯成功。有沒(méi)有辦法快速測(cè)試?
Arthas是阿里巴巴開(kāi)源的Java應(yīng)用診斷利器,深受開(kāi)發(fā)者喜愛(ài)。
下面介紹利用Arthas 3.1.0版本的?jad
/mc
/redefine
?一條龍來(lái)熱更新代碼。
Arthas: https://github.com/alibaba/arthas
jad命令: https://alibaba.github.io/arthas/jad.html
mc命令: https://alibaba.github.io/arthas/mc.html
redefine命令: https://alibaba.github.io/arthas/redefine.html
下面通過(guò)Arthas在線教程演示熱更新代碼的過(guò)程。
Arthas進(jìn)階教程
arthas-online-hotswap
在例子里,訪問(wèn)?curl http://localhost/user/0
,會(huì)返回500錯(cuò)誤:
{
????"timestamp":?1550223186170,
????"status":?500,
????"error":?"Internal?Server?Error",
????"exception":?"java.lang.IllegalArgumentException",
????"message":?"id?<?1",
????"path":?"/user/0"
}
下面通過(guò)熱更新代碼,修改這個(gè)邏輯。
反編譯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?-d?*UserController?|?grep?classLoaderHash
?classLoaderHash???1be6f5c3
可以發(fā)現(xiàn)是spring boot的?LaunchedURLClassLoader@1be6f5c3
?加載的。
保存好/tmp/UserController.java
之后,使用mc(Memory Compiler)命令來(lái)編譯,并且通過(guò)-c
參數(shù)指定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命令重新加載新編譯好的UserController.class
:
$?redefine?/tmp/com/example/demo/arthas/user/UserController.class
redefine?success,?size:?1
再次訪問(wèn)?curl http://localhost/user/0
,會(huì)正常返回:
{
????"id":?0,
????"name":?"name0"
}
Arthas里?jad
/mc
/redefine
?一條龍來(lái)線上熱更新代碼,非常強(qiáng)大,但也很危險(xiǎn),需要做好權(quán)限管理。
比如,線上應(yīng)用啟動(dòng)賬號(hào)是 admin,當(dāng)用戶可以切換到admin,那么
用戶可以修改,獲取到應(yīng)用的任意內(nèi)存值(不管是否java應(yīng)用)
用戶可以attach jvm
attach jvm之后,利用jvm本身的api可以redefine class
所以:
應(yīng)用的安全主要靠用戶權(quán)限本身的管理
Arthas主要是讓jvm redefine更容易了。用戶也可以利用其它工具達(dá)到同樣的效果
最后,Arthas提醒您:?診斷千萬(wàn)條,規(guī)范第一條,熱更不規(guī)范,同事兩行淚。
聯(lián)系客服