1.示例代码:
// JVM 配置: -Xmx20m -Xms20m -Xmn10m -XX:+PrintGCDetails
public class HellocGC {
static int _1MB = 1024 * 1024;
public static void main(String[] args) {
byte[] b1 = new byte[2 * _1MB];
//年轻代大小为10m,为什么执行完b2之后,会进行minor GC?
byte[] b2 = new byte[2 * _1MB];
byte[] b3 = new byte[2 * _1MB];
byte[] b5 = new byte[4 * _1MB];
}
}
2.GC日志:
[GC (Allocation Failure) [PSYoungGen: 6452K->1012K(9216K)] 6452K->3398K(19456K), 0.0024151 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 5512K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 54% used [0x00000000ff600000,0x00000000ffa64eb8,0x00000000ffe00000)
from space 1024K, 98% used [0x00000000ffe00000,0x00000000ffefd210,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 6482K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 63% used [0x00000000fec00000,0x00000000ff254800,0x00000000ff600000)
Metaspace used 3134K, capacity 4556K, committed 4864K, reserved 1056768K
class space used 328K, capacity 392K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:64658', transport: 'socket'
3.环境配置:
JDK版本:1.8
收集器: PS +PO
新生代大小:10M 老年代大小:10M
4.问题:
在线等待大佬回答,帮忙解惑,非常感谢。
个人思考:
1.如果该程序只有一个main()方法,那么此时内存占用为约为3M大小。详细看:https://ask.csdn.net/questions/7427712
2.程序分配b1、b2对象,因为该对象共4M大小,加上初始化的3M,新生代总大小为7M。此时新生代大小剩余1M(或者2M? 包括S0区?),已经超过90%的阀值,会触发Minor GC。因为S0区只有1M大小,无法存储新生代的7M,故走了分配担保机制,直接进入了老年代。
3.分配担保机制:在触发Minor GC时,虚拟机会校验老年代当前最大可用的连续空间是否大于新生代所有对象的总空间(10M>7M),如果此条件成立,那这次进行Minor GC则是安全的。如不成立,虚拟机会查看-XX:HandlePromotionFailure参数的设置值是否允许担保失败。如果允许,则会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的平均大小,如果大于,将尝试进行一个Minor GC,如果小于则会进行Full GC
这是个人的理解,如有偏差还请大佬指出,谢谢