zoukankan      html  css  js  c++  java
  • 常用的垃圾回收算法

    引用计数法

    对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1.
    只要A对象的引用计数器的值为0,则对象A就不可能再被使用。

    实现也很简单,只需要为每个对象配备一个整型的计数器即可。

    缺点:
    1.无法处理循环引用的情况
    2.引用计算器要求在每次引用产生和消除的时候,需要伴随一个加法操作和减法操作,对系统性能有一定影响。

    A引用了B,B又引用了A,因此A和B的引用计数器都不为0,但是系统中却 不存在任何第3个对象引用了A和B。
    这种情况下,A和B是无法被回收的,因此会引起内存泄漏。

    可达对象:指通过根对象进行引用搜索,最终可以达到的对象。
    不可达对象:通过根对象进行引用搜索,最终没有被引用到的对象。

    标记清除法

    标记清除法是现代垃圾回收算法的思想基础。

    标记清除算法将垃圾回收分为俩个阶段:
    1.标记阶段
    2.清除阶段

    一种可行的实现是:
    在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。
    然后,在清除阶段,清除所有未被标记的对象。

    缺点:容易产生空间碎片。

    回收后的空间是不连续的,在对象的堆空间分配过程中,尤其是大对象的内存分配,不连续内存空间的工作效率要低于连续的空间。

    复制算法

    核心思想:将原有的内存空间分为俩块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换俩个内存的角色,完成垃圾回收。

    如果系统中的垃圾对象很多,复制算法需要复制的存活对象数量就会相对较少,真正需要垃圾回收的时候,复制算法的效率是很高的。

    由于复制到新的内存空间中,因此可确保回收后的内存空间是没有碎片的。而复制后,在新的内存空间也会保持连续。

    缺点:
    代价是,将系统内存折半。

    Java的新生代串行垃圾回收器中,使用了复制算法的思想。新生代为eden,from,to三个部分,from/to用于存放未被回收的对象。

    在垃圾回收时,eden空间中的存活对象会被复制到未使用的survivor空间中(假设是to),正在使用的survivor空间(假设是from)中的年轻对象也会被复制到to空间,大对象或者老年对象直接进入老年代,如果to已满,则对象也会直接进入老年代。
    此时,eden和from区的剩余对象就是垃圾对象,可以直接清空。

    这种改进的复制算法,既保证了空间的连续性,又避免了大量的内存空间的浪费。

    复制算法比较适用于新生代。

    标记压缩算法

    标记压缩算法是一种老年代的回收算法。它是在标记清除算法的基础上进行了一些优化。

    在标记存活对象后,将其压缩到内存的一端,之后清理边界外的所有空间。

    1.避免了碎片的产生
    2.不需要俩块内存空间

    性价比比较高。

    等同于标记清除算法执行完成后,再进行一次内存碎片整理。

    分代算法

    将内存区间根据对象的特点分成几块,根据每块内存空间的特点,适用不同的回收算法,以提高回收的效率。

    新生代:复制算法
    老年代:标记压缩算法或标记清除算法

    分区算法

    将整个堆空间划分为连续的不同小区间,每一个小区间都独立使用,独立回收。

    好处是可以控制一次回收多少个小区间。

    一般来说,在相同条件下,堆空间越大,一次GC时所需的时间就越长,从而产生的停顿也越长,因此根据目标的停顿时间,每次合理地回收若干个小区间,而不是整个堆空间,从而减少一次GC所产生的停顿。
  • 相关阅读:
    大数减法模板
    扩展kmp模板
    poj2185(kmp)
    poj3167(kmp)
    kuangbin专题K(next数组)
    kuangbin专题16I(kmp)
    kuangbin专题16H(next数组)
    kuangbin专题16D(next求最小循环节)
    kuangbin专题16B(kmp模板)
    Java集合--TreeSet
  • 原文地址:https://www.cnblogs.com/xxdfly/p/19e28f5c981f9de0be35998519e5d402.html
Copyright © 2011-2022 走看看