Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,在使用JAVA的时候,一般不需要专门编写内存回收和垃圾清理代码。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。
Java堆内存结构划分有一定的了解。Java将堆内存分为3大部分:新生代、老年代和永久代,其中新生代又进一步划分为Eden、S0(Survivor)、S1(Survivor)三个区,并且S0,S1的大小完全相同且小于Eden区。如图所示:
+---------------------------+-------------------------------+-------------------+ | | | | | | | Eden | S0 | S1 | Old generation | Perm | | | | | | | +---------------------------+-------------------------------+-------------------+ |<----Young Gen Space------>|
我们通过New出来的对象一般在Eden区(但如果他的阈值比较大可以直接存放在老年代),当Eden区满时,就会触发对Eden的GC。他是通过把Eden区还存活的对象移动到S0或者S1区,即现在正在使用的Survivor区。这样的方法是由于超过90%的对象存活周期是很短的尔,。这就是Eden区的GC方式。
而Survivor区是当一个区间满时会触发Survivor的GC机制,它是通过他一个区里存活的对象移动端另一个区域中实现对该区域的回收。比如:当S0满时候,它会把S0里面还存活的东西移动到S1区并进行碎片化整理。当S1满时把S1里面还存活的东西移动到S0区并进行碎片化整理,循环往复(即复制算法的方式)。但当一个对象在该地方存在的时间到达某个较高的阈值事后,它就会被移动Old generation即老年代。
而Old generation区的GC机制和上诉两个地方不同。它是通过标记——整理算法来进行的。老年代都是不易被回收的对象,对象存活率高,因此一般不能直接选用复制算法。根据老年代的特点,有人提出了另外一种标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。标记-整理算法的工作过程如图: