JVM各类GC日志剖析

JerryXia 发表于 , 阅读 (0)
2016 年 03 月 15 日
jvm

在日常开发中,除了编写程序外,其他比较关注的会有垃圾收集器(GC)相关的问题,在默认的JVM行为下,可能会随着业务量或应用需求,这样的默认行为可能无法满足需求(主要可从吞吐量系统暂停响应等因素考虑),对垃圾收集器(GC)的调整,是比较普遍的,当然也可能会针对使用不同的垃圾收集器(GC)时,进一步调整一些JVM参数,如堆大小分代配额等信息,而能帮助开发人员在调整这些参数前,作一些跟踪判断的重要信息,则是垃圾收集日志。本文将详述相关的一些GC日志细节

不同的GC收集器组合

尽管在Java内存管理基础中,提到了一些常见的垃圾收集器,但在现实应用中,比较常见的组合使用大概就四种:

年轻代老年代均使用Serial GC
年轻代老年代均使用Parallel GC
年轻代使用Parallel GC年轻代使用CMS收集器。
不进行年轻代老年代区分,使用G1收集器。

为了触发各类GC组合触发垃圾收集,本文将使用如下代码:

public class GCLogDetailTest {    // 1M    private static int M_1 = 1024 * 1024;    public static void main(String[] args) {        Set<byte[]> lives = new HashSet<>();        byte[] dead = null;        dead = new byte[M_1 * 2];        System.out.println("dead allocated 2M");        dead = new byte[M_1 * 3];        System.out.println("dead allocated 3M");        lives.add(new byte[M_1 * 2]);        System.out.println("lives allocated 2M");        lives.add(new byte[M_1 * 2]);        System.out.println("lives allocated 2M");        lives.add(new byte[M_1 * 2]);        System.out.println("lives allocated 2M");        lives.add(new byte[M_1 * 2]);        System.out.println("lives allocated 2M");        lives.add(new byte[M_1 * 2]);        System.out.println("lives allocated 2M");        dead = new byte[M_1 * 2];        System.out.println("dead allocated 2M");    }}	

运行的Java环境为:

java -versionjava version "1.7.0_80"Java(TM) SE Runtime Environment (build 1.7.0_80-b15)Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)	

VM参数设置为:

-Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps {定义垃圾收集器}	

Serial GC

开发人员可通过-XX:+UseSerialGC启用Serial GC,此时,年轻代将使用标记-复制(mark-copy)算法,老年代使用标记-清理-压缩(mark-sweep-compact)算法,并且均以单线程stop-the-world的方式运行垃圾收集过程。

Minor GC日志

2016-03-14T14:57:43.807-0800: 0.260: [GC2016-03-14T14:57:43.807-0800: 0.260: [DefNew: 4185K->6K(6144K), 0.0046780 secs] 11665K->11583K(19840K), 0.0047270 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]