jvm調優神器——arthas


在上一篇《jvm調優的幾種場景》中介紹了幾種常見的jvm方面調優的場景,用的都是jdk自帶的小工具,比如jps、jmap、jstack等。用這些自帶的工具排查問題時最大的痛點就是過程比較麻煩,就好比如排查cpu占用率過高的問題,就要top->jps->printf->jstack等一系列的操作。本篇介紹一個jvm工具,它是阿里巴巴開源的一個工具——arthas(阿爾薩斯)。

一、安裝

arthas在github上有個page,地址是https://alibaba.github.io/arthas/

安裝的方式有好幾種:

  1. 直接下載一個可以啟動的jar包然后用java -jar的方式啟動
  2. 用官方提供的as.sh腳本一鍵安裝
  3. 用rpm的方式安裝

本篇介紹第一種方式,因為它簡單而且想遷移的時候也超級方便(畢竟只需要把下載的jar包拷貝走就行了)。

curl -O https://alibaba.github.io/arthas/arthas-boot.jar

如果下載速度太慢,可以用gitee上的源

curl -O https://arthas.gitee.io/arthas-boot.jar

curl命令直接把arthas-boot.jar下載到你想要的目錄

[root@localhost ~]# ll -lrt
-rw-r--r--. 1 root root   138880 Jun 22 02:55 arthas-boot.jar

二、啟動

用java命令直接啟動

[root@localhost ~]# java -jar arthas-boot.jar 
[INFO] arthas-boot version: 3.3.3
[INFO] Can not find java process. Try to pass <pid> in command line.
Please select an available pid.

但是這里啟動失敗了,這是因為arthas在啟動時會檢測本機運行的jvm進程,然后讓用戶選擇需要綁定的進程,后面的操作都是針對選定的進程的。

這里我先啟動一個java應用,然后再啟動arthas。

[root@localhost ~]# java -jar arthas-boot.jar 
[INFO] arthas-boot version: 3.3.3
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 2467 jvm-0.0.1-SNAPSHOT.jar

下面就列出了本機正在運行的java進程,等待用戶輸入,這里輸入1然后回車。如果是第一次啟動需要下載一些必要的文件,等待下載完成即可。

[root@localhost arthas]# java -jar arthas-boot.jar 
[INFO] arthas-boot version: 3.3.3
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 2467 jvm-0.0.1-SNAPSHOT.jar
1
[INFO] arthas home: /usr/local/arthas
[INFO] Try to attach process 2467
[INFO] Attach process 2467 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.                           
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'                          
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.                          
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |                         
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'                          
                                                                                

wiki      https://alibaba.github.io/arthas                                      
tutorials https://alibaba.github.io/arthas/arthas-tutorials                     
version   3.3.3                                                                 
pid       2467                                                                  
time      2020-06-22 03:02:31                                                   

[arthas@2467]$

如果看到這個界面就表示啟動並關聯成功了。

三、help命令

在arthas交互環境中,可以輸入help命令,然后會出現所有arthas支持的命令

[arthas@2467]$ help
 NAME         DESCRIPTION                      
 help         Display Arthas Help                                       
 keymap       Display all the available keymap for the specified connection.  
 sc           Search all the classes loaded by JVM       
 sm           Search the method of classes loaded by JVM      
 classloader  Show classloader info 
 jad          Decompile class 
 getstatic    Show the static field of a class     
 ...

如果不知道命令的用法,可以輸入相應的命令后加參數--help,比如可以看一下sc命令的用法

[arthas@2467]$ sc --help
 USAGE:                                    
   sc [-c <value>] [-d] [-x <value>] [-f] [-h] [-E] class-pattern                                                                                     
 SUMMARY:                                                                                                                             
   Search all the classes loaded by JVM                                                                                                       
 EXAMPLES:                                   
   sc -d org.apache.commons.lang.StringUtils   
   sc -d org/apache/commons/lang/StringUtils   
   sc -d *StringUtils                          
   sc -d -f org.apache.commons.lang.StringUtils                                        
   sc -E org\\.apache\\.commons\\.lang\\.StringUtils                                                                                  
                        
 WIKI:                                
   https://alibaba.github.io/arthas/sc                                                                                                                             
 OPTIONS:                                                
 -c, --classloader <value>                    The hash code of the special class's classLoader                                        
 -d, --details                                Display the details of class        
 -x, --expand <value>                         Expand level of object (0 by default)
 -f, --field                                  Display all the member variables 
 -h, --help                                   this help                             
 -E, --regex                                  Enable regular expression to match (wildcard matching by default)                       
 <class-pattern>                              Class name pattern, use either '.' or '/' as separator 

不僅會顯示出命令是干嘛用的,命令的完整參數,還很貼心地提供了一些具體的例子,如果英語看不習慣,還可以到WIKI下面那個地址看官方文檔,有中文版的。

四、用arthas解決上一篇的問題

(1)cpu占用過高

用thread命令列出線程的信息

[arthas@2467]$ thread
Threads Total: 28, NEW: 0, RUNNABLE: 11, BLOCKED: 0, WAITING: 14, TIMED_WAITING: 3, TERMINATED: 0                                     
ID         NAME                              GROUP                 PRIORITY   STATE      %CPU        TIME       INTERRUPTE DAEMON     
16         http-nio-8080-exec-2              main                  5          RUNNABLE   99          0:25       false      true       
29         Attach Listener                   system                9          RUNNABLE   0           0:0        false      true       
11         Catalina-utility-1                main                  1          WAITING    0           0:0        false      false      
12         Catalina-utility-2                main                  1          TIMED_WAIT 0           0:0        false      false      
28         DestroyJavaVM                     main                  5          RUNNABLE   0           0:4        false      false      
3          Finalizer                         system                8          WAITING    0           0:0        false      true       
2          Reference Handler                 system                10         WAITING    0           0:0        false      true    

這個命令會把所有線程按照cpu占用率從高到低列出來,如果線程太多,可以通過-n參數指定輸出的行數。

上面的輸出結果可以看到id為16的這個線程cpu占用率很過,然后再通過thread加線程id輸出改線程的棧信息

[arthas@2467]$ thread 16
"http-nio-8080-exec-2" Id=16 RUNNABLE
    at com.spareyaya.jvm.service.EndlessLoopService.service(EndlessLoopService.java:19)
    at com.spareyaya.jvm.controller.JVMController.endlessLoop(JVMController.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    ...

兩步就定位到了問題

(2)死鎖

還是用thread命令,參數是-b

[arthas@2997]$ thread -b
"Thread-3" Id=29 BLOCKED on java.lang.Object@3f20bf9 owned by "Thread-4" Id=30
    at com.spareyaya.jvm.service.DeadLockService.service1(DeadLockService.java:27)
    -  blocked on java.lang.Object@3f20bf9
    -  locked java.lang.Object@2fea801a <---- but blocks 1 other threads!
    at com.spareyaya.jvm.controller.JVMController.lambda$deadLock$0(JVMController.java:37)
    at com.spareyaya.jvm.controller.JVMController$$Lambda$456/748979989.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

這個命令和jstack工具檢測死鎖同樣簡單,不過個人認為jstack工具檢測死鎖其實要比這個更直觀一些。

(3)內存泄漏

這個我們可以用dashboard命令來動態查看內存情況

如果內容使用率在不斷上升,而且gc后也不下降,后面還發現gc越來越頻繁,很可能就是內存泄漏了。

這個時候我們可以直接用heapdump命令把內存快照dump出來,作用和jmap工具一樣

[arthas@23581]$ heapdump --live /root/jvm.hprof
Dumping heap to /root/jvm.hprof...
Heap dump file created

然后把得到的dump文件導入eclipse,用MAT插件分析就行了。

五、arthas其它命令

arthas還提供了很多用於監控的命令,比如監控某個方法的執行時間,反編譯線上的class文件,甚至在不重啟java應用的情況下直接替換某個類。官方的使用文檔已經寫得太詳細了,這里就不再一一介紹了,大家可以自己嘗試。

六、再說MAT工具

上一篇和本篇在排查內存泄漏的時候我們都用到了同一個工具來分析——MAT。之前我們是在eclipse中安裝了MAT插件,使用的時候只能打開eclipse來用。問題是,現在使用eclipse作為開發工具的移動互聯網公司應該很少了,我們也不想每次分析內存快照時都要啟動一個eclipse。

所以這里介紹一個MAT的獨立工具,它是獨立於eclipse的應用,下載地址是https://www.eclipse.org/mat/downloads.php,可以根據自己的系統選擇版本。

比如在windows下可以直接雙擊MemoryAnalyzer.exe啟動,啟動后可以通過頂部菜單的File->Open Heap Dump...來打開一個快照文件,也可以在welcome界面中點擊Open a Heap Dump。如果你的快照文件特別大,需要調整jvm參數,在windows下修改MemoryAnalyzer.ini文件,把-Xmx參數的值設置成適合的值(默認是1024M)。

在Overview選擇卡中,可以選擇需要分析的內容。比如可以點擊Leak Suspects分析可能的內存泄漏,也可以點擊Histogram來查看每個類的實例統計。

然后重點關注那些實例數目特別多的,或者占用內存特別多的(這個還可以設置正則表達式進行過濾,在大項目時很有用),然后結合自己的代碼看看這些對象是不是真正都需要的,還是因為作用域設置得太大了導致沒有及時回收造成。

總之,分析內存快照其實是一項費時費力的工作,在分析中積累經驗其它很重要,工具只是為了提高分析的效率。

至於像JProfile這種商業版專業的jvm分析工具,也可以去多了解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM