1. JVM 参数

  1. -XX:NewSize=10485760 -XX:MaxNewSize=10485760 -XX:InitialHeapSize=20971520 -XX:MaxHeapSize=20971520 -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:PretenureSizeThreshold=3145728 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

2. 示例代码

public class Demo3 {
    public static void main(String[] args) {
        byte[] array1 = new byte[4*1024*1024];
        array1 = null;

        byte[] array2 = new byte[2*1024*1024];
        byte[] array3 = new byte[2*1024*1024];
        byte[] array4 = new byte[2*1024*1024];
        byte[] array5 = new byte[128*1024];

        byte[] array6 = new byte[2*1024*1024];
    }
}

3. GC 日志

“0.308: [GC (Allocation Failure) 0.308: [ParNew (promotion failed): 7260K->7970K(9216K), 0.0048975 secs]0.314: [CMS:8194K->6836K(10240K), 0.0049920 secs] 11356K->6836K(19456K), [Metaspace: 2776K->2776K(1056768K)], 0.0106074 secs][Times: user=0.00 sys=0.00, real=0.01 secs]

Heap
par new generation total 9216K, used 2130K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
 eden space 8192K, 26% used [0x00000000fec00000, 0x00000000fee14930, 0x00000000ff400000)
 from space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)

concurrent mark-sweep generation total 10240K, used 6836K [0x00000000ff600000, 0x0000000100000000,0x0000000100000000)

Metaspace used 2782K, capacity 4486K, committed 4864K, reserved 1056768K
 class space used 300K, capacity 386K, committed 512K, reserved 1048576K”

image.png

  • array6 会创建2M的数组,但是 Eden 已经用了7M左右,可用不足2M,直接触发 Young GC;
  • ParNew 垃圾回收器进行回收之后,发现一个也回收不了,接近 7M 的存活对象放不下 Survivor,也放不下老年代,触发 Full GC;
    • YoungGC 之后,会先把2个2M的数组放入老年代,此时要继续放入1个2M数组和1个128KB的数组到老年代时,放不下,触发 CMS 的 Full GC;
    • ParNew (promotion failed): 7260K->7970K(9216K)

image.png

  • CMS 垃圾回收器进行 Full GC,它会进行 Old GC,Young GC,永久代 GC;
  • Young GC 之前已经触发过了,现在 CMS 执行 Old GC:
    • 先回收不再使用的 4M 数组,然后将 1个2M的数组、1个128KB的数组、未知数组放进老年代
    • CMS:8194K->6836K(10240K)
  • CMS 执行 永久代的 GC:
    • Metaspace: 2776K->2776K(1056768K)
  • CMS 执行完 Full GC 后,在新生代里分配 2M 的数组成功;

image.png