JVM运行分析

老年代GC概述

老年代GC,全称为Garbage Collection,是Java虚拟机(JVM)中的一种机制,用于回收不再使用的对象所占用的内存。在JVM的内存模型中,堆内存被划分为年轻代(新生代)和老年代。年轻代主要用于存放新创建的对象,而老年代则存放那些在年轻代中经过多次垃圾回收依然存活下来的对象。老年代GC通常指的是Full GC,它会对整个堆内存(包括年轻代和老年代)进行垃圾回收。

jstat

应用场景:日常巡检、故障排查(老年代使用率高、FGC频繁)

功能说明:检查当前进程的堆内存区域的使用率,初始化大小、GC的次数和时间等。

分析原理

分析线上的jvm进程,最想知道的信息有哪些?
包括如下:新生代对象增长的速率,VoungGc的触发频率,YoungGc的耗时,每次YoungGC后有多少对象是存活下来的,每次YoungGC过后有多少对象进入老年代,老年代对象增长的速率,FulGC的触发频率,FulGC的耗时。只要知道了这些信息,就能合理分配内存空间,尽可能让对象留在年轻代不进入老年代,避免发生频繁的FulGC。这就是对jvm最好的性能优化。

jstat -gc 进程的 GC 情况

jstat -gc 是 JDK 自带的一个轻量级工具,用于监控 Java 应用程序的资源和性能.
jstat [Options] vmid [interval] [count]
Options: 参数,指定要查看的统计信息类型。
vmid: 当前运行的 Java 进程号。
interval: 间隔时间,单位为秒或毫秒。
count: 打印次数,如果缺省则打印无数次

${JAVA_HOME}/bin/jstat -gc <pid> 1000 10 

[root@vm-855d-58a1573f1edd ~]# jstat -gc 1127 3 5 
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0  0.0   101.4  32256.0  21623.4   116224.0   60770.5   79128.0 75413.9 9760.0 8933.4    239    8.008   3      1.276    9.284
1024.0 1024.0  0.0   101.4  32256.0  21623.4   116224.0   60770.5   79128.0 75413.9 9760.0 8933.4    239    8.008   3      1.276    9.284
1024.0 1024.0  0.0   101.4  32256.0  21623.4   116224.0   60770.5   79128.0 75413.9 9760.0 8933.4    239    8.008   3      1.276    9.284
1024.0 1024.0  0.0   101.4  32256.0  21623.4   116224.0   60770.5   79128.0 75413.9 9760.0 8933.4    239    8.008   3      1.276    9.284
1024.0 1024.0  0.0   101.4  32256.0  21623.4   116224.0   60770.5   79128.0 75413.9 9760.0 8933.4    239    8.008   3      1.276    9.284

jstat -gcutil 进程垃圾回收统计情况

${JAVA_HOME}/bin/jstat -gcutil <pid> 1000 10
#每3秒,显示ID为1127的进程 垃圾回收统计情况,总共显示 5 次
[root@vm-855d-58a1573f1edd ~]# jstat -gcutil 1127 3000 5
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00   9.90  67.04  52.29  95.31  91.53    239    8.008     3    1.276    9.284
  0.00   9.90  67.04  52.29  95.31  91.53    239    8.008     3    1.276    9.284
  0.00   9.90  67.04  52.29  95.31  91.53    239    8.008     3    1.276    9.284
  0.00   9.90  67.04  52.29  95.31  91.53    239    8.008     3    1.276    9.284
  0.00   9.90  67.04  52.29  95.31  91.53    239    8.008     3    1.276    9.284

jdk7版本参数说明

E年轻代使用率
O老年代使用率
P持久代使用率
YGC年轻代GC的次数
YGCT年轻代GC的总时间(单位ms)
FGC堆全局GC的次数
FGCT堆GC的总时间(单位ms)
GCT年轻代和堆GC的总时间(单位ms)

jdk8版本参数说明

列名含义
S0幸存者区 0 当前使用比例
S1幸存者区 1 当前使用比例
E年轻代使用率
O老年代使用率
MMetaspace 当前使用比例
CCS压缩使用比例
YGC年轻代垃圾回收次数
YGCT年轻代垃圾回收消耗时间
FGC老年代垃圾回收次数
FGCT老年代垃圾回收消耗时间
GCT垃圾回收消耗总时间

FGCT/FGC是FullGC的平均时间,平均时间越长,S-T-W(暂停用户线程执行)的时间就越长,对用户请求的影响就越大,如果用户请求感觉到有明显的卡顿,就需要调整JVM参数配置。

jstat -gcold 进程统计 GC 时老年代的情况

[root@vm-855d-58a1573f1edd ~]# jstat -gcold 1127 3000 5
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT   
 79128.0  75413.9   9760.0   8933.4    116224.0     60770.5    239     3    1.276    9.284
 79128.0  75413.9   9760.0   8933.4    116224.0     60770.5    239     3    1.276    9.284
 79128.0  75413.9   9760.0   8933.4    116224.0     60770.5    239     3    1.276    9.284
 79128.0  75413.9   9760.0   8933.4    116224.0     60770.5    239     3    1.276    9.284
 79128.0  75413.9   9760.0   8933.4    116224.0     60770.5    239     3    1.276    9.284


jmap

jmap-heappid

如果只是要了解vm的运行状况,然后去优化jvm参数,一般来说jstat就完全可以了。但有时
候我们会发现jvm新增对象的速度很快,然后我们想知道到底是什么对象占用了那么多的内存。
我们先来看一个命令:jmap-heappid,执行结果如下图

[root@vm-855d-58a1573f1edd ~]# jmap -heap 1127
Attaching to process ID 1127, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.281-b09

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 2092957696 (1996.0MB)
   NewSize                  = 44040192 (42.0MB)
   MaxNewSize               = 697303040 (665.0MB)
   OldSize                  = 88080384 (84.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 = 33030144 (31.5MB)
   used     = 22681784 (21.63103485107422MB)
   free     = 10348360 (9.868965148925781MB)
   68.66995190817212% used
From Space:
   capacity = 1048576 (1.0MB)
   used     = 103840 (0.099029541015625MB)
   free     = 944736 (0.900970458984375MB)
   9.9029541015625% used
To Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
PS Old Generation
   capacity = 119013376 (113.5MB)
   used     = 62229040 (59.34623718261719MB)
   free     = 56784336 (54.15376281738281MB)
   52.28743364107241% used

42448 interned Strings occupying 5395024 bytes.

jmap -histo

使用jmap了解系统运行时的对象分布

[root@vm-855d-58a1573f1edd ~]# jmap -histo 1127 | head -n10

 num     #instances         #bytes  class name
----------------------------------------------
   1:        300918       29256760  [C
   2:        245030        5880720  java.lang.String
   3:         95230        3809200  java.util.HashMap$KeyIterator
   4:         38867        3420296  java.lang.reflect.Method
   5:         32569        3272104  [B
   6:         10139        2605440  [I
   7:         55181        1765792  java.util.concurrent.ConcurrentHashMap$Node

这个就有点意思了,它会按照各对象占用内存空间的大小降序排列,把占用内存最大的对象放在最上面。所以通过该命令,你可以快速定位到当前内存里是哪个对象占用了大量的内存空间。

如果你觉得仅仅只是看个大概还不够,想要来点深入和仔细点的,那就可以用jmap生成一个堆内存快照放到一个文件里去,用如下命令即可:

jmap -dump:live,format=b,fi1e=dump.hprof pid

这个命令会在当前目录下生成一个dump.hprof文件,这是二进制的格式,你不能直接打开看,它把这一时刻jvm堆内存里所有对象的快照放到文件里去了,供你后续分析。

jhat

使用jhat在浏览器中分析堆转出的快照,jhat内置 web服务器,它会支持你通过浏览器以图形化的方式分析堆快照。使用如下命令即可启动jhat服务器,还可以指定自己想要的http端口号,默认是7000端口号。

jhat dump.hprof

然后就可以在浏览器上访问这台机器的7000端口号,就可以通过图形化的方式去分析堆内存里的对象分布情况了。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容