JVM各类GC日志剖析
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]