GC相关内存
可以从下面一张图来理解一下JVM内存的划分:
JVM的分配策略
对象优先分配在 Eden,首先尝试在 Eden 分配。
- 如果Eden 空间不足,就发起 YoungGC(简称YGC);
- 如果幸存对象(被根对象直接或间接引用)在 SurvivorTo 能放下,则存活对象全部移入 SurvivorTo;
- 如果幸存对象在 SurvivorTo 存放不下,则存活对象全部移入老年代;
- 如果此时老年代空间不足,则发起一次 FullGC(简称FYC,整个系统停顿,老年代也参与回收);
- 如果 FullGC 时空间仍然周转不过来,则报 OutOfMemoryError 并导致进程结束;
- 如果YGC/FGC能周转过来,则新对象分配在 Eden 中;
大对象直接分配在老年代,所谓的大对象是指,需要大量连续内存的 Java 对象,尤其是长字符串或数组,比如 byte[n] 对象;可以指定多大才算大对象(只对 Serial/ParNew 有效);
长期存活对象移入老年代,经历 n 次 YGC 仍然存活的对象,下次 YGC 时将被移入老年代;
永久代满了也会导致 FullGC。老年代、永久代的垃圾收集是捆绑在一起的,因此无论两者谁满了,都会触发两者的FullGC。
动态对象年龄判定。如果 Survivor 相同年龄对象占用空间达到一半,则大于等于该年龄的对象都移入老年代。
冒险模式。JDK 6u24 之后,总是开启冒险模式(先尝试 YGC,以免 FGC 频繁);
- 每次 YGC 之前,如果老年代最大连续空间,大于新生代所有对象空间之和,则 YGC 肯定成功,否则:
- 如果老年代最大连续空间,大于历次晋升老年代的平均值,则先冒险尝试 YGC;
- 如果老年代最大连续空间,小于历次晋升老年代的平均值,则直接 FullGC;
JVM优化原则
目标:
- 尽量减少 YoungGC,以减少代码停顿
- 尽量减少 FullGC,以减少系统停顿
方法:
- 缩短对象生命期,尤其是大对象
- 优化JVM参数以减少YGC/FGC次数,可替换收集器
JVM相关命令
jstat -gcutil pid
YGC 对新生代堆进行gc。频率比较高,因为大部分对象的存活寿命较短,在新生代里被回收.性能耗费较小。FGC 全堆范围的gc。默认堆空间使用到达80%(可调整)的时候会触发FGC,进行FGC时最好在零晨等业务少的时候进行,例:
[root@test11 ~]# jstat -gcutil 18834
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
29.39 0.00 93.18 39.15 97.65 93.10 8 0.139 1 0.064 0.202
释义:
S0: 幸存者空间0利用率占空间当前容量的百分比。
S1: 幸存者空间1占空间当前容量的百分比。
E: 伊甸园空间利用率占空间当前容量的百分比。
O: 旧空间利用率占空间当前容量的百分比。
M: 元空间利用率占空间当前容量的百分比。
CCS: 压缩的类空间利用率百分比。
YGC: 年轻一代GC事件的数量。
YGCT: 年轻一代垃 圾收集时间。
FGC: 完整GC事件的数量。
FGCT: 完全垃圾收集时间。
GCT: 垃圾总时间。
jstat -gc pid
垃圾回收统计,例:
[root@test11 ~]# jstat -gc 18834
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
8704.0 8704.0 2558.1 0.0 208896.0 193121.8 39424.0 15432.9 26368.0 25748.9 2816.0 2621.7 8 0.139 1 0.064 0.202
释义:
S0C: 第一个幸存区的大小
S1C: 第二个幸存区的大小
S0U: 第一个幸存区的使用大小
S1U: 第二个幸存区的使用大小
EC: 伊甸园区的大小
EU: 伊甸园区的使用大小
OC: 老年代大小
OU: 老年代使用大小
MC: 方法区大小
MU: 方法区使用大小
CCSC: 压缩类空间大小
CCSU: 压缩类空间使用大小
YGC: 年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC: 老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT: 垃圾回收消耗总时间
jstat -gccapacity pid
堆内存统计,例:
[root@test11 ~]# jstat -gccapacity 18834
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
20480.0 323584.0 231424.0 8704.0 8704.0 208896.0 40960.0 647168.0 39424.0 39424.0 0.0 1073152.0 26368.0 0.0 1048576.0 2816.0 8 1
释义:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC: 当前新生代容量
S0C: 第一个幸存区大小
S1C: 第二个幸存区的大小
EC: 伊甸园区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC: 当前老年代大小
OC: 当前老年代大小
MCMN: 最小元数据容量
MCMX: 最大元数据容量
MC: 当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC: 当前压缩类空间大小
YGC: 年轻代gc次数
FGC: 老年代GC次数
jstat -gcnew pid
新生代垃圾回收统计,例:
[root@test11 ~]# jstat -gcnew 18834
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
8704.0 8704.0 2558.1 0.0 3 15 8704.0 208896.0 196312.6 8 0.139
释义:
S0C: 第一个幸存区大小
S1C: 第二个幸存区的大小
S0U: 第一个幸存区的使用大小
S1U: 第二个幸存区的使用大小
TT: 对象在新生代存活的次数
MTT: 对象在新生代存活的最大次数
DSS: 期望的幸存区大小
EC: 伊甸园区的大小
EU: 伊甸园区的使用大小
YGC: 年轻代垃圾回收次数
YGCT: 年轻代垃圾回收消耗时间
jstat -gcnewcapacity pid
新生代内存统计,例:
[root@test11 ~]# jstat -gcnewcapacity 18834
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
20480.0 323584.0 231424.0 107520.0 8704.0 107520.0 8704.0 322560.0 208896.0 8 1
释义:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数
jstat -gcold pid
老年代垃圾回收统计,例:
[root@test11 ~]# jstat -gcold 18834
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
26368.0 25748.9 2816.0 2621.7 39424.0 15432.9 8 1 0.064 0.202
释义:
MC: 方法区大小
MU: 方法区使用大小
CCSC: 压缩类空间大小
CCSU: 压缩类空间使用大小
OC: 老年代大小
OU: 老年代使用大小
YGC: 年轻代垃圾回收次数
FGC: 老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT: 垃圾回收消耗总时间
jstat -gcoldcapacity pid
老年代内存统计,例:
[root@test11 ~]# jstat -gcoldcapacity 18834
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
40960.0 647168.0 39424.0 39424.0 8 1 0.064 0.202
释义:
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC: 当前老年代大小
OC: 老年代大小
YGC: 年轻代垃圾回收次数
FGC: 老年代垃圾回收次数
FGCT: 老年代垃圾回收消耗时间
GCT: 垃圾回收消耗总时间
jstat -class pid
类加载统计,例:
[root@test11 ~]# jstat -class 18834
Loaded Bytes Unloaded Bytes Time
3614 7870.8 0 0.0 1.66
释义:
Loaded: 加载class的数量
Bytes: 所占用空间大小
Unloaded:未加载数量
Bytes: 未加载占用空间
Time: 时间
jstat -compiler pid
编译统计,例:
[root@test11 ~]# jstat -compiler 18834
Compiled Failed Invalid Time FailedType FailedMethod
2675 0 0 9.82 0
释义:
Compiled: 编译数量。
Failed: 失败数量
Invalid: 不可用数量
Time: 时间
FailedType: 失败类型
FailedMethod:失败的方法
jstack -l pid
查看java 的线程个数:jstack -l pid | grep -c “java.lang.Thread.State:”(控制tomcat的线程个数)
查看java 的线程状态:jstack -l pid | grep “java.lang.Thread.State:”,状态如下:
- 死锁 Deadlock(重要)
- 等待资源 Waiting on condition (重要)
- 等待获取监视器waiting on monitor entry
- 阻塞Blocked
- 执行中Runnable
- 暂停Suspended
- 对象等待中Object.wait()或TIMED_WAITING
- 停止Parked