《深入理解Java虚拟机》(二)--垃圾收集器与内存分配策略(2)

垃圾收集算法:

1/1 标记-清除算法(Mark-Sweep):

最基础的垃圾回收算法,它分为两个阶段,标记和清除:首先它会标记出所有需要回收的对象,在标记完成之后统一回收所有被标记对象,它的标记过程之前已经提到了。

缺点:

1、效率低:它的标记和清除两个过程效率都不高。
2、空间问题:因为标记和清除之后会产生大量的不连续的片段,空间碎片太多可能会导致以后需要分配大对象的过程中,由于无法找到足够的连续内存而不得不提前触发一次垃圾收集。
具体过程如下:


12350543-3e66997808c40c25.png
标记-清除算法的具体过程

1/2 复制算法(Copying):

复制算法是将可用的内存按照容量大小分为相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将上面还存活的对象复制到另一块没用过的内存中,然后清理之前使用过的内存。

优点:

这样的算法使得每次都对整个半区进行内存回收,内存分配时也不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。

缺点:

这种算法的代价是将能够使用的内存缩小为原来的一半,浪费的资源太多了。
具体的过程如下:


12350543-e7f74130af5c75c4.png
复制算法的具体执行过程
新生代和老年代:

新生代指的是频繁出生和死亡的对象区域,相反老年代的对象都比较稳定。

改进:

其实新生代中的大部分对象是“朝生夕死”,生命很短,也就是说存活的对象很少,所以并不需要按照1:1的比例去分配内存空间,在HotSpot虚拟机中,是将一块内存分为一块较大的内存空间Eden和两块较小的空间Survivor,他们的默认比例是8:1:1,每次使用的是Eden和其中的一块Survivor。当回收时,将Eden和那块Survivor中还存活的对象(因为是新生代,所以很少)全部复制到另一块Survivor中,最后清理掉刚才所使用的Eden和Survivor,这样每次只有10%会被“浪费掉”,解决了浪费资源太多的问题。虽然新生代中的存活对象很少,但有的时候还是会超过那10%的内存空间,当那块Survivor空间不够用的时候,这些对象将直接通过分配担保机制进入老年代。

1/3 标记-整理算法(Mark-Compact):

如果在对象存活情况较多的时候(老年代中),显然,复制收集算法的效率会很低,为了应对这种情况,老年代中一般选用标记-整理算法。
标记整理算法的标记过程与标记清除算法一样,但是后续的步骤是将存活的对象向着内部的边界(比如上边)移动,也就是说移动完之后,存活的对象都紧挨着,然后直接清除掉存活对象以外的对象。
具体过程如下:


12350543-90195b12fb53e98f.png
标记-整理算法的具体过程

1/4 分代收集算法:

分代收集算法并不是一种特定的算法,它是根据对象存活周期的不同将内存划分为几块,一般是将Java堆分成新生代和老年代,这样根据各个年代的特点选择最适合的垃圾收集算法,新生代中对象频繁的创建和死去,就使用复制算法,老年代的对象比较稳定,就使用标记-清除或者标记-整理算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章