Java 虚拟机 Jvm 堆内存分配
堆内存是 JVM 一块重点的区域,我们所说的 JVM 调优也是这一块。
1. 内存分配
在jdk1.7版本中堆内存被划分为三块:新生代、老年代、持久代。
新生代又主要分为:Eden区(伊甸园)、From Survivor区(幸存区0)、To Survivor区(幸存区1)。JVM默认分配空间为 8:1:1。也就是说Eden的空间分配是最大的。
2. 对象分配
我们新创建的对象实例首先会放在 新生代的Eden区(伊甸园)。
1.1. 大对象分配
我们也可以设置JVM参数将新创建对象实例放入老年代中。
虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。
其目是为让新生代更好的运行。新生代采用的是复制算法下面会为大家讲述。
1.2. 新生代的运行
新创建的对象会放在Eden区(伊甸园),当Eden空间满了的时候会进行GC操作。称之为Minor GC。
1.Eden区(伊甸园)满了进行Minor GC进行空间清理死亡的对象。将Eden区(伊甸园)清理完后的对象复制到 S0(幸存者),S1为空。
2.当下一次 Eden 满了触发Minor GC时,清理Eden空间死亡对象,将存活对象复制到S1(幸存区)。同时,将清理S0(幸存区)空间死亡对象,将存活对象复制到S1。清空S0
Survivor区总有一个(幸存区)为空。
jvm给每个对象都分配了一个年龄,每次Minor GC对象就会+1。
jvm -XX:MaxTenuringThreshold 默认为15,也就是说对象年龄大于15就会进入老年代。我们也可以设置这个参数。
注意:当发生Minor GC的时候,发现Survivor空间不足,部分对象无法复制到Survivor区,虚拟机通过分配担保机制将这些对象提前转移到老年代。有兴趣可以看看这个担保机制。