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分析工具,也可以去多了解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 垃圾收集器分类 串行收集器->Serial和Serial Old只能有一个垃圾回收线程执行,用户线程暂停适用于'内...
    竹blue阅读 805评论 0 1
  • 1. 概述 内存泄漏:一块内存被占用后未释放,程序后续不在使用这块内存内容,导致这块内存一直被占用。内存溢出:OO...
    _空格键_阅读 381评论 0 0
  • 参数设置 在Java虚拟机的参数中,有3种表示方法用“ps -ef |grep "java"命令,可以得到当前Ja...
    九问阅读 9,108评论 2 52
  • 工具做为图形化界面来展示更能直观的发现问题,另一方面一些耗费性能的分析(dump文件分析)一般也不会在生产直接分析...
    Java_Explorer阅读 2,931评论 0 21
  • ​16年的时候花了一些时间整理了一些关于jvm的介绍文章,到现在回顾起来还是一些还没有补充全面,其中就包括如何利用...
    王知无阅读 827评论 0 9