前言:对象的内存分配,大方向讲,指的是对象在堆上分配,对象的主要分配发生在新生代的Eden区,当然少数分配在老年代,分配的规则并不是固定不变的,细节取决于具体的虚拟机实现。
——对象优先在Eden区分配
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发生一次Minor GC
虚拟机提供 -XX:PrintGCDetails这个收集器日志参数,告诉虚拟机在发生GC行为时打印内存回收日志,并且在进程退出时候输出当前运行时内存各区域的分配情况。
案例演示:
主方法中,尝试分配3个2MB大小和1个4MB大小的对象,
通过-Xms20M -Xmx20M -Xmn10M 这3个参数限制了Java堆的大小为20MB,不可拓展,其中10MB分配给新生代,剩下10MB分配给老年代。
通过-XX:SurvivorRatio=8决定新生代中Eden区与一个Survivor区间大小比为8:1
public class testAllocation {
private static final int _1MB=1024*1024;
/*
* VM启动参数
*
* -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
*
*
*
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
byte[] allocation1,allocation2,allocation3,allocation4;
allocation1=new byte[2*_1MB];
allocation2=new byte[2*_1MB];
allocation3=new byte[2*_1MB];
allocation4=new byte[4*_1MB]; //将出现Minor GC
}
}
打印的GC日志:
可以看到前面3个大小为2MB的对象分配在Eden区内 但最后一个4MB对象无法分配在Eden区,而选择分配在ParOldGen
也就是老年代 将对象4分配取消
//allocation4=new byte[4*_1MB]; //将出现Minor GC
结果:
发现Eden区空间充足,所有3个对象全在Eden区内分配
由此可见 虚拟机在普通对象分配时,优先在新生代Eden区分配,当空间不足时会在老年代分配