这节简单聊一聊对象内存分配。
之前讲过Java堆中可以细分为:新生代和老年代;再细致一点的有Eden空间、 From Survivor空间、 To Survivor空间等。而对象内存分配大方向上就是在堆上分配。对象主要分配在新生代的Eden区,少数也可能直接分配到老年代中。
首先了解下Minor GC和Full GC。
新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。
老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。 Major GC的速度一般会比Minor GC慢10倍以上。
好了,现在介绍下不同情况下的对象是如何内存分配。
一:对象优先分配在Eden区。大多数情况下,对象在新生代Eden区中分配。 当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。发生Minor GC时,将Eden区中的对象放入Survivor区,当Eden区中的对象无法放入Survivor区时才会通过分配担保机制(何为担保机制可以自己去了解下)提前转移到老年代。
二:大对象直接进入老年代。大对象就是需要连续内存空间的Java对象,比如很长的字符串或数组。
三:长期存活对象进入老年代。为了能识别哪些对象应放在新生代,哪些放在老年代,虚拟机给每个对象定义了一个对象年龄,该年龄是对象在放入Eden区并经历一次Minor GC后仍然存活,在转移到Survivor区后,默认设置年龄为1,之后每经过一次Minor GC后年龄+1,到默认15岁后,虚拟机认为此对象比较稳定,将此对象转移到老年代中。这个默认15可以通过参数-XX:
MaxTenuringThreshold设置。
四:动态对象年龄判定。虚拟机不是完全根据第三点将对象存入老年代,如果Survivor区空间中相同年龄所有对象大小的总和大于Survivor空间的一半,那这些年龄大于或等于该年龄的对象会转移到老年代,不需要等到默认的15岁。
本文讲解了Java对象在堆上的分配策略,包括新生代与老年代的分配原则、MinorGC与FullGC的区别及触发条件、对象如何从Eden区迁移至Survivor区或老年代的过程,并介绍了大对象直接分配到老年代的情况。

被折叠的 条评论
为什么被折叠?



