JVM调优排错(解析&实际案例)

1,020 阅读3分钟

前言

本案例只是简单介绍JVM排查工具,调优措施,以及普遍示例简单解析。(更完整命令可以参考:docs.oracle.com/javase/7/do…)

一. 常用工具

1. jmap

jmap命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。 使用示例:

  1. jmap -histo $PID --> 显示堆中对象的统计信息 image.png

其中instance表示元素出现的个数,bytes表示元素所占内存大小(单位kb)

  1. jamp -heap $PID --> 显示Java堆详细信息
Attaching to process ID 31370, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.45-b02

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 492830720 (470.0MB)
   NewSize                  = 10485760 (10.0MB)
   MaxNewSize               = 164102144 (156.5MB)
   OldSize                  = 20971520 (20.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 7864320 (7.5MB)
   used     = 5038400 (4.80499267578125MB)
   free     = 2825920 (2.69500732421875MB)
   64.06656901041667% used
From Space:
   capacity = 5767168 (5.5MB)
   used     = 131072 (0.125MB)
   free     = 5636096 (5.375MB)
   2.272727272727273% used
To Space:
   capacity = 6291456 (6.0MB)
   used     = 0 (0.0MB)
   free     = 6291456 (6.0MB)
   0.0% used
PS Old Generation
   capacity = 117964800 (112.5MB)
   used     = 78530512 (74.89253234863281MB)
   free     = 39434288 (37.60746765136719MB)
   66.57113986545139% used

  1. jmap -dump:live,format=b,file=dumpfile $PID --> 生成堆转储快照dump文件

或jmap -dump:live,format=b,file=heapdump.hprof $PID,hprof方便通过mat解析。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。(执行较为耗时)

2. jstack

jstack是java虚拟机自带的一种堆栈跟踪工具。常用于分析线程问题(如线程间死锁[deadLock]) 使用示例:

  1. jstack -l $PID > /tmp/dump/jstack.log --> 导出堆栈信息

-l :会打印出额外的锁信息 image.png

  1. 找出java进程中消耗CPU最多的线程TID
  • 结合top命令可以查出占用CPU最高的线程: top -H -p pid

详细输出可以使用:ps p {pid}-L -o pcpu,pid,tid,time,tname,cmd

  • 将TID转化成十六进制: printf 0x%x n
  • 从jstack.log 文件中找出TID对应的16进制数据

3. jstat

JVM statistics Monitoring,用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译(即使编译)等运行数据。

  1. jstat -gc $PID --> 获取垃圾回收等信息

image.png

 结果分析:(C一般是容量,U结尾一般是使用量)
 堆内存 = 年轻代 + 年老代 + 永久代
 年轻代 = Eden区 + 两个SurvivorS0CS1CS0US1USurvivor 0/1区容量(Capacity)和使用量(UsedECEUEden区容量和使用量
 OCOU:年老代容量和使用量
 PCPU:永久代容量和使用量
 YGCYGT:年轻代GC次数和GC耗时
 FGCFGCTFull GC次数和Full GC耗时
 GCTGC总耗时

clipboard.png

引言:JVM配置中除了常用的xmx,xms
-Xmn、-XX:NewRatio、-XX:SurvivorRatio:

-   -Xmn

**设置新生代大小**

-   -XX:NewRatio

    新生代(eden+2*s)和老年代(不包含永久区)的比值

        例如:4,表示新生代:老年代=1:4,即新生代占整个堆的1/5

-   -XX:SurvivorRatio(幸存代)

    设置两个Survivor区和eden的比值

        例如:8,表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10
  1. GC结果分析 ygc平均耗时=YGCT/YGC(s)=5176.81/469204=0.011s=11ms ygc时间间隔=YGC/程序的运行时间
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;
如果GC时间超过13 秒,或者频繁G C ,则必须优化。如果满足下面的指标,则一般不需要进行GC;
■ Minor GC执行时间不到50ms;\
■ Minor GC执行不频繁,约10秒一次;\
■ Full GC执行时间不到1s;\
■ Full GC执行频率不算频繁,不低于10分钟1次。