34.堆内存分配策略(或对象提升(Promotion)规则)总结(掌握)
1.堆内存分配策略(或对象提升(Promotion)规则)
一般情况下的策略:
1.对象会被优先分配到Eden
区
2.大对象,如果Eden
区放不下,就会被直接放到老年代
3.长期存活的对象(Survivor
区中的对象的age
超过阈值的对象),会被放到老年代
4.动态年龄判断。如果Survivor
区中的相同年龄的所有对象大小的总和大于Survivor
空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无须等到MaxTenuringThreshold
中要求的年龄。比如说年龄为5
的所有的对象的大小总和超过了Survivor
空间的一半,那么这些对象就会被直接放到老年代。
大对象直接分配到老年代例子:
在运行下面的代码之前,设置下面的JVM参数: -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails
a)堆空间的大小为60M
,新生代和老年代的比例为1:2
。可以得到新生代为20M
。
b)Eden区:S0:S1
为8:1:1
,所以Eden
区为16M
。
package jvn; /** 测试:大对象直接进入老年代 * -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails */ public class YoungOldAreaTest { public static void main(String[] args) { byte[] buffer = new byte[1024 * 1024 * 20];//20m } }
得到输出如下:
上面的代码开辟了一个20M
的数组对象。Eden
区是放不下的,会直接放到老年代。
从下面的 ParOldGen total 40960K, used 20480K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000)
就可以看出来。老年代used
的空间是20480K
也就是20M
。
Heap PSYoungGen total 18432K, used 1639K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000) eden space 16384K, 10% used [0x00000000fec00000,0x00000000fed99d00,0x00000000ffc00000) from space 2048K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x0000000100000000) to space 2048K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x00000000ffe00000) ParOldGen total 40960K, used 20480K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000) object space 40960K, 50% used [0x00000000fc400000,0x00000000fd800010,0x00000000fec00000) Metaspace used 2548K, capacity 4486K, committed 4864K, reserved 1056768K class space used 279K, capacity 386K, committed 512K, reserved 1048576K