JVM调优工具锦囊:JDK自带工具与Arthas线上分析工具对比

Arthas线上分析诊断调优工具

以前我们要排查线上问题,通常使用的是jdk自带的调优工具和命令。最常见的就是dump线上日志,然后下载到本地,导入到jvisualvm工具中。这样操作有诸多不变,现在阿里团队开发的Arhtas工具,拥有非常强大的功能,并且都是线上的刚需,尤其是情况紧急,不方便立刻发版,适合临时处理危急情况使用。下面分两部分来研究JVM性能调优工具:

1.JDK自带的性能调优工具

虽然有了Arthas,但也不要忘记JDK自带的性能调优工具,在某些场景下,他还是有很大作用的。而且Arthas里面很多功能其根本就是封装了JDK自带的这些调优命令。

2.Arthas线上分析工具的使用

这一部分,主要介绍几个排查线上问题常用的方法。功能真的很强大,刚兴趣的猿媛可以研究其基本原理。之前跟我同事讨论,感觉这就像病毒一样,可以修改内存里的东西,真的还是挺强大的。

以上两种方式排查线上问题,没有优劣之分,如果线上不能安装Arthas就是jdk自带命令,如果jdk自带命令不能满足部分要求,又可以安装Arthas,那就使用Arthas。他们只是排查问题的工具,重要的是排查问题的思路。不管黑猫、白猫,能抓住耗子就是好猫。

一、JDK自带的调优工具

这里不是流水一样的介绍功能怎么用,就说说线上遇到的问题,我们通常怎么排查,排查的几种情况。

  • 内存溢出,出现OutOfMemoryError,这个问题如何排查
  • CPU使用猛增,这个问题如何排查?
  • 进程有死锁,这个问题如何排查?
  • JVM参数调优

下面来一个一个解决

1、处理内存溢出,报OutOfMemoryError错误

第一步:通过jmap -histo命令查看系统内存使用情况

使用的命令:

jmap -histo 进程号

运行结果:

num     #instances         #bytes  class name
----------------------------------------------
	 1:       1101980      372161752  [B
   2:        551394      186807240  [Ljava.lang.Object;
   3:       1235341      181685128  [C
   4:         76692      170306096  [I
   5:        459168       14693376  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
   6:        543699       13048776  java.lang.String
   7:        497636       11943264  java.util.ArrayList
   8:        124271       10935848  java.lang.reflect.Method
   9:        348582        7057632  [Ljava.lang.Class;
  10:        186244        5959808  java.util.concurrent.ConcurrentHashMap$Node
  8671:      1             16  zipkin2.reporter.Reporter$1
  8672:      1             16  zipkin2.reporter.Reporter$2

Total       8601492      923719424                                   
                                     
                                     
num:序号
instances:实例数量
bytes:占用空间大小
class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]

通过这个命令,我们可以看出当前哪个对象最消耗内存。

上面这个运行结果是我启动了本地的一个项目,然后运行【jmap -histro 进程号】运行出来的结果,直接去了其中的一部分。通过这里我们可以看看大的实例对象中,有没有我们自定义的实例对象。通过这个可以排查出哪个实例对象引起的内存溢出。

除此之外,Total汇总数据可以看出当前一共有多少个对象,暂用了多大内存空间。这里是有约860w个对象,占用约923M的空间。

第二步:分析内存溢出,查看堆空间占用情况

使用命令

jhsdb jmap --heap --pid 进程号

比如,我本地启动了一个项目,想要查看这个项目的内存占用情况:

[root@iZ2pl8Z ~]# jhsdb jmap --heap --pid 28692
  
Attaching to process ID 28692, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0.13+10-LTS-370

using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 2065694720 (1970.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 1239416832 (1182.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 1970
   capacity = 2065694720 (1970.0MB)
   used     = 467303384 (445.65523529052734MB)
   free     = 1598391336 (1524.3447647094727MB)
   22.622093161955704% used
G1 Young Generation:
Eden Space:
   regions  = 263
   capacity = 464519168 (443.0MB)
   used     = 275775488 (263.0MB)
   free     = 188743680 (180.0MB)
   59.36794582392776% used
Survivor Space:
   regions  = 6
   capacity = 6291456 (6.0MB)
   used     = 6291456 (6.0MB)
   free     = 0 (0.0MB)
   100.0% used
G1 Old Generation:
   regions  = 179
   capacity = 275775488 (263.0MB)
   used     = 186285016 (177.65523529052734MB)
   free     = 89490472 (85.34476470947266MB)
   67.54951912187352% used

下面来看看参数的含义

堆空间配置信息

Heap Configuration:
  /**
   * 空闲堆空间的最小百分比,计算公式为:HeapFreeRatio =(CurrentFreeHeapSize/CurrentTotalHeapSize) * 100,值的区间为0	  * 到100,默认值为 40。如果HeapFreeRatio < MinHeapFreeRatio,则需要进行堆扩容,扩容的时机应该在每次垃圾回收之后。
   */
	MinHeapFreeRatio = 40  
  /**
   * 空闲堆空间的最大百分比,计算公式为:HeapFreeRatio =(CurrentFreeHeapSize/CurrentTotalHeapSize) * 100,值的区间为0  
   * 到100,默认值为 70。如果HeapFreeRatio > MaxHeapFreeRatio,则需要进行堆缩容,缩容的时机应该在每次垃圾回收之后
   */
  MaxHeapFreeRatio         = 70
  /**JVM 堆空间允许的最大值*/
  MaxHeapSize              = 2065694720 (1970.0MB)
  /** JVM 新生代堆空间的默认值*/
  NewSize                  = 1363144 (1.2999954223632812MB)
  /** JVM 新生代堆空间允许的最大值 */
  MaxNewSize               = 1239416832 (1182.0MB)
  /** JVM 老年代堆空间的默认值 */
  OldSize                  = 5452592 (5.1999969482421875MB)
  /** 新生代(2个Survivor区和Eden区 )与老年代(不包括永久区)的堆空间比值,表示新生代:老年代=1:2*/
  NewRatio                 = 2
  /** 两个Survivor区和Eden区的堆空间比值为 8,表示 S0 : S1 :Eden = 1:1:8 */
  SurvivorRatio            = 8
  /** JVM 元空间的默认值 */
  MetaspaceSize            = 21807104 (20.796875MB)
  CompressedClassSpaceSize = 1073741824 (1024.0MB)
  /** JVM 元空间允许的最大值 */
  MaxMetaspaceSize         = 17592186044415 MB
  /** 在使用 G1 垃圾回收算法时,JVM 会将 Heap 空间分隔为若干个 Region,该参数用来指定每个 Region 空间的大小 */
  G1HeapRegionSize         = 1048576 (1.0MB) 

G1堆使用情况

Heap Usage:
G1 Heap:
   regions  = 1970
   capacity = 2065694720 (1970.0MB)
   used     = 467303384 (445.65523529052734MB)
   free     = 1598391336 (1524.3447647094727MB)
   22.622093161955704% used
     
G1 的 Heap 使用情况,该 Heap 包含 1970 个 Region,结合上文每个 RegionSize=1M,因此 Capacity = Regions * RegionSize = 1970 * 1M = 1970M,已使用空间为 445.65M,空闲空间为 1524.34M,使用率为 22.62%。

G1年轻代Eden区使用情况

G1 Young Generation:
Eden Space:
   regions  = 263
   capacity = 464519168 (443.0MB)
   used     = 275775488 (263.0MB)
   free     = 188743680 (180.0MB)
   59.36794582392776% used

     
     
G1 的 Eden 区的使用情况,总共使用了 263 个 Region,结合上文每个 RegionSize=1M,因此 Used = Regions * RegionSize = 263 * 1M = 263M,Capacity=443M 表明当前 Eden 空间分配了 443 个 Region,使用率为 59.37%。

G1年轻代Survivor区使用情况和G1老年代使用情况:和Eden区类似

Survivor Space:
   regions  = 6
   capacity = 6291456 (6.0MB)
   used     = 6291456 (6.0MB)
   free     = 0 (0.0MB)
   100.0% used
     
G1 Old Generation:
   regions  = 179
   capacity = 275775488 (263.0MB)
   used     = 186285016 (177.65523529052734MB)
   free     = 89490472 (85.34476470947266MB)
   67.54951912187352% used
     
Survivor区使用情况和Eden区类似。 老年代参数含义和Eden区类似。

通过上面的命令,我们就能知道当前系统对空间的使用情况了,到底是老年代有问题还是新生代有问题。

第三步:导出dump内存溢出的文件,导入到jvisualvm查看

如果前两种方式还是没有排查出问题,我们可以导出内存溢出的日志,在导入客户端进行分析

使用的命令是:

jmap -dump:file=a.dump 进程号

或者是直接设置JVM参数

-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=./ (路径)

然后导入到jvisualvm中进行分析,方法是:点击文件->装入ÿ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值