老年代GC概述
老年代GC,全称为Garbage Collection,是Java虚拟机(JVM)中的一种机制,用于回收不再使用的对象所占用的内存。在JVM的内存模型中,堆内存被划分为年轻代(新生代)和老年代。
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 | 老年代使用率 |
M | Metaspace 当前使用比例 |
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端口号,就可以通过图形化的方式去分析堆内存里的对象分布情况了。
暂无评论内容