读书笔记之四:垃圾回收算法

一、标记 - 清除算法(Mark - Sweep)

       标记 - 清除算法分为“标记”和“清除”两个阶段:

       首先标记出需要回收的对象,在标记完成后统一回收所有被标记的对象,它的标记过程也就是判断对象是不是垃圾对象,可以参考之前的文章 -- 判断对象是否存活https://www.cnblogs.com/lveyHang/p/11834028.html

       这种回收算法的缺点:

       1.1 效率问题

       标记和清除两个过程的效率都不高。

       1.2 空间问题

       标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

image

二、复制算法(Copying)

       2.1 背景

       为了解决标记-清除算法的效率问题,出现了复制算法。

       2.2 算法实现

       将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活的对象复制到另外一块内存上,然后把已使用过的内存空间一次清理掉。这样使得每次都对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可。

       2.3 优缺点

       实现简单,运行高效。但是,这种算法的代价是将内存缩小为了原来的一半。

       2.4 虚拟机上的使用

       现在的商业虚拟机都采用这种收集算法来回收新生代,IBM 公司的研究表明,新生代中的对象 98% 是“朝生夕死”的,因此不需要按照 1 :1 的比例来划分内存空间,而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。当回收时,将 Eden 和 Survivor 中存活着的对象一次性地复制到另外一块 Survivor 空间上,最后清理掉 Eden 和 刚才使用过的 Survivor 空间。HotSpot 虚拟机默认 Eden 和 Survivor 的大小比例是 8 :1,也就是每次新生代中可用内存空间为整个新生代容量的 90%(80% + 10%),只有 10% 的内存会被“浪费”。

       当 Survivor 空间没有足够空间存放上一次新生代收集下来的存活对象时,这些对象将直接通过分配担保机制(Handle Promotion)进入老年代。

image

三、标记 - 整理算法(Mark - Compact)

       3.1 背景

       复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。如果不想浪费 50% 的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都 100% 存活的极端情况,因此老年代一般不能直接选用复制算法。

       3.2 算法实现

       “标记 - 整理”算法的标记过程仍然与“标记 - 清除”算法一样,然后让所有存活的对象都向一端移动,再直接清理掉端边界以外的内存就可以了。

image

posted @ 2019-11-13 21:51  辰凩風  阅读(139)  评论(0编辑  收藏  举报