Minor GC和Full GC触发条件

原文地址:https://blog.csdn.net/shi2huang/article/details/80067608

在复制原文作者内容前先对Full GC条件做一个补充。

执行jmap histo命令也可能会出发Full GC(Heap Inspection Initiated GC)。以及Dump堆内存也会发生GC

下图的GC日志有一次Full GC,GC原因是Heap Inspection Initiated GC(堆检查导致GC)。最终通过https://blog.csdn.net/wisgood/article/details/51477512 这篇文章的提示,可能是使用了jmap histo命令导致的Full  GC,我想到正在使用JMC监控应用程序,经过验证,在使用JMC的MBean服务器->内存->堆直方图这个功能时,每次刷新直方图都会调用jmap histo这个命令,而这个命令将会导致Full GC。此外比较扯淡的是此次Full GC 将年轻代的对象全部弄到老年代去了(通过日志可以看出)。

 

 

--------------------------------------------以下是原文内容------------------------------

一、Minor GC触发条件
     1、eden区满时,触发MinorGC。即申请一个对象时,发现eden区不够用,则触发一次MinorGC。

      注:新生代分为三个区域,eden space, from space, to space。默认比例是8:1:1。在MinorGC时,会把存活的对象复制到to space区域,如果to space区域不够,则利用担保机制进入老年代区域。

     对eden space, from space, to space的理解:每次分配eden space空间,如果不够,则小于 to space大小的对象复制到 to space,然后to space和from space换位置,所以我们看到的to space一直是空的。

测试代码:

    private static final int _1M = 1024 * 1024;
 
    private static void testMinorGC() {
 
        /* eden space为8M,from/to space各为1M */
        LargeObject largeOb1 = new LargeObject(_1M * 1 / 2, "largeOb1");
        LargeObject largeOb2 = new LargeObject(_1M * 1, "largeOb2");
        LargeObject largeOb3 = new LargeObject(_1M * 2, "largeOb3");
        largeOb3 = null;
        LargeObject largeOb4 = new LargeObject(_1M * 3, "largeOb4");
        LargeObject largeOb5 = new LargeObject(_1M * 2, "largeOb5");
    }
 
    public static void main(String[] agrs) {
        testMinorGC();
    }
 
    static class LargeObject {
        private byte[] data;
        private String name;
 
        public LargeObject(int size, String name) {
            data = new byte[size];
            this.name = name;
            System.out.println("Over Constructing LargeObject " + name + System.lineSeparator());
        }
 
        public String getName() {
            return name;
        }
    }
测试环境:JDK1.8.0_144,Java HotSpot(TM) 64-Bit Server VM,默认垃圾收集器为PS Scavenge+PS MarkSweep。

-Xms30m -Xmx30m -Xmn10m -XX:+PrintGCDetails -XX:+PrintHeapAtGC

 堆总大小为30m,新生代为10m,打印GC信息,在GC前后打印内存信息。在eclipse下运行参考eclipse设置运行JVM参数。

打印结果及分析:

Over Constructing LargeObject largeOb1
 
Over Constructing LargeObject largeOb2
 
Over Constructing LargeObject largeOb3
 
Over Constructing LargeObject largeOb4
 
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 7640K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 93% used [0x00000000ff600000,0x00000000ffd760d8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 0K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 0% used [0x00000000fe200000,0x00000000fe200000,0x00000000ff600000)
 Metaspace       used 2777K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
// 实例化largeOb1、largeOb2、largeOb3、largeOb4共使用了eden space 6656K ,从上面信息可以看到eden space还剩余573m,初始化LargeOb5时,需要2048K。
// 由于eden space不够给新的对象分配内存,所以触发一次MinorGC。
// 7640K->1000K(9216K,eden space+from space),新生代GC结果从7640K变成了1000K,这时新生代只存在largeOb1对应的内存,因为largeOb1对应的内存为0.5M,小于to space区大小,进入from space?不太懂。
// largeOb2和largeOb4由于对应的大于to space区大小,担保进入到老年代。
// 7640K->5232K(29696K,eden space+from space+ParOldGen),总的内存占用变化,回收了2408K空间。
// largeOb3之前的内存没有引用(largeOb3=null),所以被回收了。
[GC (Allocation Failure) [PSYoungGen: 7640K->1000K(9216K)] 7640K->5248K(29696K), 0.0030601 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 7640K->616K(9216K)] 7640K->5232K(29696K), 0.0031851 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
 
 
// 回收之后的内存情况,可以看到from space存在largeOb1,ParOldGen存在largeOb2和largeOb4。
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 616K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 60% used [0x00000000ffe00000,0x00000000ffe9a020,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 4616K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 22% used [0x00000000fe200000,0x00000000fe682030,0x00000000ff600000)
 Metaspace       used 2777K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb5
 
// 分配完largeOb5,可以看到largeOb5的内存被分配在了新生代的eden space。
Heap
 PSYoungGen      total 9216K, used 2906K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 27% used [0x00000000ff600000,0x00000000ff83ca88,0x00000000ffe00000)
  from space 1024K, 60% used [0x00000000ffe00000,0x00000000ffe9a020,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 4616K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 22% used [0x00000000fe200000,0x00000000fe682030,0x00000000ff600000)
 Metaspace       used 2784K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 300K, capacity 386K, committed 512K, reserved 1048576K

 2、Full GC之前调用,仅适用于Parallel Scavenge(-XX:+UseParallelGC),虚拟机运行在Server模式下的默认收集器组合。
      判断一个对象是否存活,除了GC Roots引用之外,还有一个条件就是对象是否重写了finalize方法,如果对象重写了该方法,则会交给FQueue队列去执行,如果执行该方法后被重新关联,则在下次回收时不会被回收,否则下次回收,该方法只执行一次。

测试代码:

    private static final int _1M = 1024 * 1024;
 
    private static void testMinorGCOverriddeFinalize() {
 
 
        /* Eden区为8M,from/to space各为1M */
        LargeObjectOverrideFinalize largeOb1 = new LargeObjectOverrideFinalize(_1M * 1 / 2, "largeOb1");
        LargeObjectOverrideFinalize largeOb2 = new LargeObjectOverrideFinalize(_1M * 1, "largeOb2");
        LargeObjectOverrideFinalize largeOb3 = new LargeObjectOverrideFinalize(_1M * 2, "largeOb3");
        largeOb1 = null;
        largeOb3 = null;
        LargeObjectOverrideFinalize largeOb4 = new LargeObjectOverrideFinalize(_1M * 3, "largeOb4");
        LargeObjectOverrideFinalize largeOb5 = new LargeObjectOverrideFinalize(_1M * 2, "largeOb5");
 
 
        /* 保证调用finalize完毕 */
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
 
        System.gc();
    }
 
    public static void main(String[] agrs) {
        testMinorGCOverriddeFinalize();
    }
 
    static class LargeObjectOverrideFinalize {
        private byte[] data;
        private String name;
 
        public LargeObjectOverrideFinalize(int size, String name) {
            data = new byte[size];
            this.name = name;
            System.out.println("Over Constructing LargeObjectOverrideFinalize " + name + System.lineSeparator());
        }
 
        public String getName() {
            return name;
        }
 
        @Override
        public void finalize() {
            System.out.println(
                    "Finalize LargeObjectOverrideFinalize " + name + " , release " + (data.length / 1024) + "K.");
        }
    }
测试环境:JDK1.8.0_144,Java HotSpot(TM) 64-Bit Server VM,默认垃圾收集器为PS Scavenge+PS MarkSweep。

-Xms30m -Xmx30m -Xmn10m -XX:+PrintGCDetails -XX:+PrintHeapAtGC     

堆总大小为30m,新生代为10m,打印GC信息,在GC前后打印内存信息。

打印结果及分析:

Over Constructing LargeObjectOverrideFinalize largeOb1
 
Over Constructing LargeObjectOverrideFinalize largeOb2
 
Over Constructing LargeObjectOverrideFinalize largeOb3
 
Over Constructing LargeObjectOverrideFinalize largeOb4
 
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 7640K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 93% used [0x00000000ff600000,0x00000000ffd760d8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 0K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 0% used [0x00000000fe200000,0x00000000fe200000,0x00000000ff600000)
 Metaspace       used 2774K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
// 对比未实现finalize方法的回收情况,实现了finalize方法的对象都没有被回收
[GC (Allocation Failure) [PSYoungGen: 7640K->736K(9216K)] 7640K->7400K(29696K), 0.0047814 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 736K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 71% used [0x00000000ffe00000,0x00000000ffeb8030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 6664K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 32% used [0x00000000fe200000,0x00000000fe882040,0x00000000ff600000)
 Metaspace       used 2774K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
}
Finalize LargeObjectOverrideFinalize largeOb1 , release 512K.
Finalize LargeObjectOverrideFinalize largeOb3 , release 2048K.
Over Constructing LargeObjectOverrideFinalize largeOb5
 
{Heap before GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 3108K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 28% used [0x00000000ff600000,0x00000000ff8510f0,0x00000000ffe00000)
  from space 1024K, 71% used [0x00000000ffe00000,0x00000000ffeb8030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 6664K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 32% used [0x00000000fe200000,0x00000000fe882040,0x00000000ff600000)
 Metaspace       used 2775K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
// 调用System.gc()之后先进行一次MinorGC,largeOb1在from space区域,largeOb3在ParOldGen,所以这次只把largeOb5放入了老年代。
[GC (System.gc()) [PSYoungGen: 3108K->712K(9216K)] 9772K->9424K(29696K), 0.0059394 secs] [Times: user=0.05 sys=0.02, real=0.01 secs] 
Heap after GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 712K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 69% used [0x00000000fff00000,0x00000000fffb2050,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 8712K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 42% used [0x00000000fe200000,0x00000000fea82050,0x00000000ff600000)
 Metaspace       used 2775K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
}
{Heap before GC invocations=3 (full 1):
 PSYoungGen      total 9216K, used 712K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 69% used [0x00000000fff00000,0x00000000fffb2050,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 8712K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 42% used [0x00000000fe200000,0x00000000fea82050,0x00000000ff600000)
 Metaspace       used 2775K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
// Full GC把from space的largeOb1回收,老年代回收了largeOb3。
[Full GC (System.gc()) [PSYoungGen: 712K->0K(9216K)] [ParOldGen: 8712K->6696K(20480K)] 9424K->6696K(29696K), [Metaspace: 2775K->2775K(1056768K)], 0.0186298 secs] [Times: user=0.06 sys=0.00, real=0.02 secs] 
Heap after GC invocations=3 (full 1):
 PSYoungGen      total 9216K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 6696K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 32% used [0x00000000fe200000,0x00000000fe88a260,0x00000000ff600000)
 Metaspace       used 2775K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K
}
Heap
 PSYoungGen      total 9216K, used 82K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 1% used [0x00000000ff600000,0x00000000ff614920,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 6696K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 32% used [0x00000000fe200000,0x00000000fe88a260,0x00000000ff600000)
 Metaspace       used 2781K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 300K, capacity 386K, committed 512K, reserved 1048576K
注:如果逃脱垃圾回收参考使用finalize逃脱垃圾回收。

二、Full GC触发条件

1、老生代空间不够分配新的内存

测试代码:

    private static final int _1M = 1024 * 1024;
 
    private static void testFullGC() {
 
        /* Eden区为8M,from/to space各为1M */
        LargeObject largeOb1 = new LargeObject(_1M * 8, "largeOb1");
        largeOb1 = null;
        LargeObject largeOb2 = new LargeObject(_1M * 15, "largeOb2");
    }
 
    public static void main(String[] agrs) {
            testFullGC();
    }
 
    static class LargeObject {
        private byte[] data;
        private String name;
 
        public LargeObject(int size, String name) {
            data = new byte[size];
            this.name = name;
            System.out.println("Over Constructing LargeObject " + name + System.lineSeparator());
        }
 
        public String getName() {
            return name;
        }
    }
测试环境:JDK1.8.0_144,Java HotSpot(TM) 64-Bit Server VM,默认垃圾收集器为PS Scavenge+PS MarkSweep。

-Xms30m -Xmx30m -Xmn10m -XX:+PrintGCDetails -XX:+PrintHeapAtGC     

堆总大小为30m,新生代为10m,打印GC信息,在GC前后打印内存信息。

打印结果及分析:

注意Full GC原因,Full GC (Allocation Failure),分配失败。

Over Constructing LargeObject largeOb1
 
 
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 1148K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 14% used [0x00000000ff600000,0x00000000ff71f3d8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 8192K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 40% used [0x00000000fe200000,0x00000000fea00010,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 1148K->704K(9216K)] 9340K->8904K(29696K), 0.0008682 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 704K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 68% used [0x00000000ffe00000,0x00000000ffeb0030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 8200K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 40% used [0x00000000fe200000,0x00000000fea02010,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
{Heap before GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 704K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 68% used [0x00000000ffe00000,0x00000000ffeb0030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 8200K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 40% used [0x00000000fe200000,0x00000000fea02010,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 704K->720K(9216K)] 8904K->8920K(29696K), 0.0006179 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 720K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 70% used [0x00000000fff00000,0x00000000fffb4040,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 8200K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 40% used [0x00000000fe200000,0x00000000fea02010,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
 
{Heap before GC invocations=3 (full 1):
 PSYoungGen      total 9216K, used 720K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 70% used [0x00000000fff00000,0x00000000fffb4040,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 8200K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 40% used [0x00000000fe200000,0x00000000fea02010,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 两次Minor GC之后空间还是不够,触发Full GC。回收largeOb1内存。
[Full GC (Allocation Failure) [PSYoungGen: 720K->0K(9216K)] [ParOldGen: 8200K->560K(20480K)] 8920K->560K(29696K), [Metaspace: 2864K->2864K(1056768K)], 0.0103751 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
Heap after GC invocations=3 (full 1):
 PSYoungGen      total 9216K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 560K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 2% used [0x00000000fe200000,0x00000000fe28c290,0x00000000ff600000)
 Metaspace       used 2864K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb2
 
Heap
 PSYoungGen      total 9216K, used 246K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 3% used [0x00000000ff600000,0x00000000ff63d890,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 15920K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 77% used [0x00000000fe200000,0x00000000ff18c2a0,0x00000000ff600000)
 Metaspace       used 2870K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 312K, capacity 386K, committed 512K, reserved 1048576K
 
为什么有两次Minor GC?测试了换其它收集器就不会有。

2、System.gc(),见Minor GC触发条件的第2点。

3、通过Minor GC后进入老年代的平均大小大于老年代的可用内存。

测试代码:

    private static final int _1M = 1024 * 1024;
 
    /**
     * 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
     */
    private static void testFullGCNewAveMore() {
 
        /* Eden区为8M,from/to space各为1M */
        LargeObject largeOb1 = new LargeObject(_1M * 2, "largeOb1");
        LargeObject largeOb2 = new LargeObject(_1M * 4, "largeOb2");
        LargeObject largeOb3 = new LargeObject(_1M * 2, "largeOb3");
        LargeObject largeOb4 = new LargeObject(_1M * 4, "largeOb4");
        LargeObject largeOb5 = new LargeObject(_1M * 2, "largeOb5");
        LargeObject largeOb6 = new LargeObject(_1M * 4, "largeOb6");
        LargeObject largeOb7 = new LargeObject(_1M * 2, "largeOb7");
    }
 
    public static void main(String[] agrs) {
        testFullGCNewAveMore();
    }
 
    static class LargeObject {
        private byte[] data;
        private String name;
 
        public LargeObject(int size, String name) {
            data = new byte[size];
            this.name = name;
            System.out.println("Over Constructing LargeObject " + name + System.lineSeparator());
        }
 
        public String getName() {
            return name;
        }
    }
测试环境:JDK1.8.0_144,Java HotSpot(TM) 64-Bit Server VM,默认垃圾收集器为PS Scavenge+PS MarkSweep。

-Xms30m -Xmx30m -Xmn10m -XX:+PrintGCDetails -XX:+PrintHeapAtGC     

堆总大小为30m,新生代为10m,打印GC信息,在GC前后打印内存信息。

打印结果及分析:

注意Full GC原因,Full GC (Ergonomics) ,意思不太懂。

Over Constructing LargeObject largeOb1
 
Over Constructing LargeObject largeOb2
 
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f3f8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 0K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 0% used [0x00000000fe200000,0x00000000fe200000,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 第一次Minor GC,6152K进入老年代。
[GC (Allocation Failure) [PSYoungGen: 7292K->648K(9216K)] 7292K->6800K(29696K), 0.0028600 secs] [Times: user=0.05 sys=0.02, real=0.00 secs] 
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 648K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 63% used [0x00000000ffe00000,0x00000000ffea2020,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 6152K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 30% used [0x00000000fe200000,0x00000000fe802020,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb3
 
Over Constructing LargeObject largeOb4
 
{Heap before GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 6952K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 76% used [0x00000000ff600000,0x00000000ffc280c0,0x00000000ffe00000)
  from space 1024K, 63% used [0x00000000ffe00000,0x00000000ffea2020,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 6152K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 30% used [0x00000000fe200000,0x00000000fe802020,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 第二次Minor GC,6144K进入老年代。
[GC (Allocation Failure) [PSYoungGen: 6952K->632K(9216K)] 13104K->12928K(29696K), 0.0056290 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap after GC invocations=2 (full 0):
 PSYoungGen      total 9216K, used 632K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 61% used [0x00000000fff00000,0x00000000fff9e030,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 12296K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 60% used [0x00000000fe200000,0x00000000fee02040,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb5
 
Over Constructing LargeObject largeOb6
 
{Heap before GC invocations=3 (full 0):
 PSYoungGen      total 9216K, used 6936K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 76% used [0x00000000ff600000,0x00000000ffc28038,0x00000000ffe00000)
  from space 1024K, 61% used [0x00000000fff00000,0x00000000fff9e030,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 12296K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 60% used [0x00000000fe200000,0x00000000fee02040,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 第三次Minor GC,6144K进入老年代。
[GC (Allocation Failure) [PSYoungGen: 6936K->632K(9216K)] 19232K->19072K(29696K), 0.0030912 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=3 (full 0):
 PSYoungGen      total 9216K, used 632K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 61% used [0x00000000ffe00000,0x00000000ffe9e030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 18440K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 90% used [0x00000000fe200000,0x00000000ff402060,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
{Heap before GC invocations=4 (full 1):
 PSYoungGen      total 9216K, used 632K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 61% used [0x00000000ffe00000,0x00000000ffe9e030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 18440K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 90% used [0x00000000fe200000,0x00000000ff402060,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 前三次平均每次进入老年代的大小是6144K,大于老年代剩余大小2040K,触发一次Full GC。
[Full GC (Ergonomics) [PSYoungGen: 632K->0K(9216K)] [ParOldGen: 18440K->18991K(20480K)] 19072K->18991K(29696K), [Metaspace: 2868K->2868K(1056768K)], 0.0577421 secs] [Times: user=0.05 sys=0.00, real=0.06 secs] 
Heap after GC invocations=4 (full 1):
 PSYoungGen      total 9216K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 18991K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 92% used [0x00000000fe200000,0x00000000ff48bf10,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb7
 
Heap
 PSYoungGen      total 9216K, used 2372K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 28% used [0x00000000ff600000,0x00000000ff851090,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 20480K, used 18991K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 92% used [0x00000000fe200000,0x00000000ff48bf10,0x00000000ff600000)
 Metaspace       used 2874K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 312K, capacity 386K, committed 512K, reserved 1048576K
4、Minor GC时,eden space和from space区大小大于to space且大于老年代内存,触发Full GC。

测试代码:

    private static final int _1M = 1024 * 1024;
 
    /**
     * Minor GC时,eden space和from space区大小大于to space且大于老年代内存,触发Full GC。
     */
    private static void testFullGCOldGenLessEden() {
 
        /* Eden区为8M,from/to space各为1M */
        
        // 8M进入老年代,老年代使用8M
        LargeObject largeOb1 = new LargeObject(_1M * 8, "largeOb1");
    
        // 8M进入老年代,老年代使用16M        
        LargeObject largeOb2 = new LargeObject(_1M * 8, "largeOb2");
 
        // 4M进入新生代,新生代使用4M        
        LargeObject largeOb3 = new LargeObject(_1M * 4, "largeOb3");
        
        // 4M进入新生代,新生代使用6M
        LargeObject largeOb4 = new LargeObject(_1M * 2, "largeOb4");
        
        // 新生代空间不足,触发MinorGC,新生代的6M老年代装不下,触发Full GC
        LargeObject largeOb5 = new LargeObject(_1M * 1, "largeOb5");
    }
 
    public static void main(String[] agrs) {
        testFullGCOldGenLessEden();
    }
 
    static class LargeObject {
        private byte[] data;
        private String name;
 
        public LargeObject(int size, String name) {
            data = new byte[size];
            this.name = name;
            System.out.println("Over Constructing LargeObject " + name + System.lineSeparator());
        }
 
        public String getName() {
            return name;
        }
    }
测试环境:JDK1.8.0_144,Java HotSpot(TM) 64-Bit Server VM,默认垃圾收集器为PS Scavenge+PS MarkSweep。

-Xms30m -Xmx30m -Xmn10m -XX:+PrintGCDetails -XX:+PrintHeapAtGC     

堆总大小为30m,新生代为10m,打印GC信息,在GC前后打印内存信息。

打印结果及分析:

注意Full GC原因,Full GC (Ergonomics) ,意思不太懂。

Over Constructing LargeObject largeOb1
 
Over Constructing LargeObject largeOb2
 
Over Constructing LargeObject largeOb3
 
Over Constructing LargeObject largeOb4
 
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f0a0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 16384K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 80% used [0x00000000fe200000,0x00000000ff200020,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 申请largeOb5时,eden space剩余900K,不足1024K,所以触发Minor GC。
[GC (Allocation Failure) --[PSYoungGen: 7292K->7292K(9216K)] 23676K->23684K(29696K), 0.0012875 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f0a0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 63% used [0x00000000ffe00000,0x00000000ffea2020,0x00000000fff00000)
 ParOldGen       total 20480K, used 16392K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 80% used [0x00000000fe200000,0x00000000ff202020,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
{Heap before GC invocations=2 (full 1):
 PSYoungGen      total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f0a0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 63% used [0x00000000ffe00000,0x00000000ffea2020,0x00000000fff00000)
 ParOldGen       total 20480K, used 16392K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 80% used [0x00000000fe200000,0x00000000ff202020,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
// 上一次Minor GC时,由于eden space+from space大小大于老年代剩余大小,不能分配到老年代,触发Full GC。
[Full GC (Ergonomics) [PSYoungGen: 7292K->6703K(9216K)] [ParOldGen: 16392K->16385K(20480K)] 23684K->23088K(29696K), [Metaspace: 2868K->2868K(1056768K)], 0.0078789 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] 
Heap after GC invocations=2 (full 1):
 PSYoungGen      total 9216K, used 6703K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 81% used [0x00000000ff600000,0x00000000ffc8bea0,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 16385K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 80% used [0x00000000fe200000,0x00000000ff200540,0x00000000ff600000)
 Metaspace       used 2868K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 311K, capacity 386K, committed 512K, reserved 1048576K
}
Over Constructing LargeObject largeOb5
 
Heap
 PSYoungGen      total 9216K, used 7973K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 97% used [0x00000000ff600000,0x00000000ffdc9740,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 20480K, used 16385K [0x00000000fe200000, 0x00000000ff600000, 0x00000000ff600000)
  object space 20480K, 80% used [0x00000000fe200000,0x00000000ff200540,0x00000000ff600000)
 Metaspace       used 2874K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 312K, capacity 386K, committed 512K, reserved 1048576K
5、Metaspace空间不足。不知如何演示。
--------------------- 
作者:抱抱- 
来源:CSDN 
原文:https://blog.csdn.net/shi2huang/article/details/80067608 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值