我们需要采用如下参数来运行上述程序:
运行之后会得到如下GC日志:
一行一行看代码
这行代码直接分配了一个4MB的大对象,大于JVM参数设置的大对象阈值,此时这个对象会直接进入老年代,接着array1不再引用这个对象。
接着会执行如下代码:
这个对象肯定是不能放进eden区了,因为eden区里已经放了6MB+128KB的对象了,总共就8MB,放不下这个2MB对象了。
所以此时会直接触发一次Young GC。
ParNew (promotion failed): 7260K->7970K(9216K), 0.0048975 secs
因为eden区对象都有人引用,所以回收不掉。
所以此时大家都知道,一定会直接把这些对象放入到老年代里去,但是此时老年代里已经有一个4MB的数组了,还能 放的下3个2MB的数组和1个128KB的数组吗?
答案是:肯定不行了,都超了内存了。
所以要对老年代进行gc
所以此时我们看gc日志:
[CMS: 8194K->6836K(10240K), 0.0049920 secs] 11356K->6836K(19456K), [Metaspace: 2776K->2776K(1056768K)], 0.0106074 secs]
大家可以清晰看到,此时执行了CMS垃圾回收器的Full GC,我们之前讲过Full GC其实就是会对老年代进行Old GC, 同时一般会跟一次Young GC关联,还会触发一次元数据区(永久代)的GC。
在CMS Full GC之前,就已经触发过Young GC了,此时大家可以看到此时Young GC就已经有了,接着就是执行针对 老年代的Old GC,也就是上面的日志:
此时要继续放1个2MB的数组(array2,3,4中的一个)和1个128KB的数组(array5)到老年代,一定会放不下,所以此时就会触发CMS的Full GC,
然后此时就会回收掉其中的一个4MB的数组,因为他已经没人引用了,如下图所示。
接着放入进去1个2MB的数组和1个128KB的数组,如下图所示。
所以大家再看CMS的垃圾回收日志:CMS: 8194K->6836K(10240K), 0.0049920 secs,他是从回收前的8MB变成了 6MB,就是上图所示。
最后在CMS Full GC执行完毕之后,其实年轻代的对象都进入了老年代,此时最后一行代码要在年轻代分配2MB的数 组就可以成功了,如下图。
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!