GC

来源:互联网 发布:令狐冲知乎 编辑:程序博客网 时间:2024/05/19 14:19

1、什么是Minor GC、Major GC和Full GC

Minor GC:从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC。

Major GC:是清理老年代。

Full GC:是清理整个堆空间—包括年轻代和老年代。这次GC是发生了Stop-The-World。

2、full gc触发条件

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法区空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

3、GC触发的条件

(1)程序调用System.gc时可以触发;(2)系统自身来决定GC触发的时机。

4、如何发现是否发生FULL GC和FULL GC是否频繁

使用JDK自带的轻量级小工具jstat
     语法结构:
Usage: jstat -help|-options
             jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

参数解释:
Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid    — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count   — 打印次数,如果缺省则打印无数次
比如 /opt/taobao/java/bin/jstat –gcutil pid 5000

5、FULL GC分析和问题定位

a.     GC log收集和分析
(1)在JVM启动参数增加:"-verbose:gc -Xloggc:<file_name>  -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
    PrintGCTimeStamp只能获得相对时间,建议使用PrintGCDateStamps获得full gc 发生的绝对时间
      (2)如果采用CMS GC,仔细分析jstat FGC输出和GC 日志会发现, CMS的每个并发GC周期则有两个stop-the-world阶段——initial mark与final re-mark,使得CMS的每个并发GC周期总共会更新full GC计数器两次,initial mark与final re-mark各一次
   
    b.     Dump JVM 内存快照
/opt/taobao/java/bin/jmap -dump:format=b,file=dump.bin pid
这里有一个问题是什么时候进行dump?
一种方法是前面提到的用jstat工具观察,当OLD区到达比较高的比例如60%,一般会很快触发一次FULL GC,可以进行一次DUMP,在FULL GC发生以后再DUMP一次,这样比较就可以发现到底是哪些对象导致不停的FULL GC
另外一种方法是通过配置JVM参数
-XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC分别用于指定在full GC之前与之后生成heap dump

    c.     利用MAT((Memory Analyzer Tool)工具分析dump文件
关于MAT具体使用方法网上有很多介绍,这里不做详细展开,这里需要注意的是:
(1)   MAT缺省只分析reachable的对象,unreachable的对象(将被收集掉的对象)被忽略,而分析FULL GC频繁原因时unreachable object也应该同时被重点关注。如果要显示unreachable的对象细节必须用mat 1.1以上版本并且打开选项“keep unreachable object”
(2)   通常dump文件会好几个G,无法在windows上直接进行分析,我们可以先把dump文件在linux上进行分析,再把分析好的文件拷贝到windows上,在windows上用MAT打开分析文件。

6、Full GC本身不会先进行Minor GC,可以配置

-XX:+ScavengeBeforeFullGC(非CMS回收算法)、CMSScavengeBeforeRemark(CMS回收算法)可以,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,先进行一次Minor GC可以提高老年代GC的速度。

(G1回收算法除外,G1回收有一个MIXED回收阶段,新生代和老年代都一起回收,与配置的JVM参数无关)