引用计数法
方法:
每个对象有一个对应的计数字段。每有一个引用指向它,则计数加1。每删除一个指向它的引用,则计数减1。Gc只回收标记为0的对象。
优点:
1. 垃圾回收的cpu开销分布在程序运行期间,很“平滑”,无需挂起应用程序就可以进行垃圾回收。
2. 当对象引用变为0时,系统无需访问内存中的其它页面,就可以回收。
3. 废弃即回收,不像一些算法,对象废弃后都会存在一段时间才被回收。
缺陷:
1. 每当对象创建、删除和引用改变时都需要维护这个记录字段。
2. 每个对象需要有额外的空间存放引用计数。
3. 无法处理循环引用。即A引用B,B同时也引用A时,A和B都无法被回收。
使用:
Python作为脚本语言,经常要与c/c++这些语言交互,使用引用计数算法可以避免改变对象在内存中位置,而python为了解决环形引用问题也引入了gc模块,所以本质上python的gc方案是混合了引用计数和跟踪两种垃圾回收机制。
评价:
这种方法垃圾收集较快,适用于实时环境,它是垃圾回收的早期策略,现在很少用。
跟踪法
把每个对象看作图中一个节点,对象之间的引用关系为图中各节点的邻接关系。垃圾收集器从一个或数个根结点遍历对象图,如果有些对象节点永远无法到达,则这个对象可以被当作垃圾回收。
标记—清除
方法:
算法分为两个阶段。第一是从引用根节点开始标记所有被引用的对象,第二是遍历整个堆,把未标记的对象清除。
优点:
1. 很自然的处理了循环引用的问题
2. 对象的创建的消毁时不需要进行额外的维护。
缺陷:
1. 回收过程会暂停整个应用程序。
2. 需要遍历所有的活动对象。
3. 会产生大量内存碎片。
标记—压缩
方法:
标记—清除的改进。在第二阶段把标记对象复制到堆的一端,另一端的就是连续区。
优点:
1. 解决内存碎片问题
缺陷:
1. 移动后需要对每个对象的引用进行更新,使这些引用可以识别新位置上的对象。
标记—复制
方法:
标记—清除的改进。这种收集器将堆栈分为两个域,称为半空间。每次仅使用一半的空间,虚拟机生成的新对象则放在另一半空间中。垃圾回收器运行时,它把可到达对象复制到另一半空间,没有被复制的的对象都是不可达对象,可以被回收。
优点:
1. 解决内存碎片问题
缺陷:
1. 对象生存期长时,它会被多次复制,影响效率。
2. 每次只有一半的虚拟机空间可用。
3. 移动后需要对每个对象的引用进行更新,使这些引用可以识别新位置上的对象。
增量回收
方法:
把堆分成多个域,每次只对一个域进行回收。
优点:
1. 造成较小的应用程序中断。
分代回收
方法:
把堆分成几个域,用以存放不同寿命的对象。每次生成的新对象放入一个域中。过一段时间后继续存在的对象会转入更长寿命的域中。
优点:
1. 可以针对不同的域使用不同的回收策略,避免了压缩和复制策略中寿命长的对象被反复复制的效率问题。