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
文档更新时间: 2019-08-01 18:23   作者:子木