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

    前面介绍了如何去识别和标记垃圾,现在主要介绍,如何去回收(处理、删除)这些垃圾?

    你也许会想,找到了直接删掉不就行了吗?

    恭喜你,已经学会了一个很重要的算法。

    标记-清除(Mark-Sweep)

    标记-清除算法,主要分为两个步骤,标记 和 清除。标记,就使用之前说过的 可达性分析算法,即可进行标记。

    就是我们根据 GC Roots 标记出存活对象,然后将垃圾对象进行清除即可。

    就是这么简单。

    但是这种算法主要有如下缺点:

    会产生大量的内存碎片。内存空间不再连续,对于一些大对象连续的对象结构来说,无非是浪费内存的行为。

    标记-复制

    为了解决上面的问题,内存碎片的问题,有种算法叫做垃圾-复制算法出现了。

    注意,我们将一个大内存分为 A B 两个部分。然后在一个内存中进行数据的存储。然后进行垃圾回收的时候,将标记出来的存活对象,直接复制到 B 空闲内存中,复制完成后,A 内存的全部空间都是可用的了。

    在介绍其缺点之前,先明确一点:

    只要移动了存活对象,相对而言,都会比较耗时,这个是由 Java 内存对象存储结构决定的。

    这就是Java 存储对象的结构布局,首先栈中保存指向Java堆中的引用,然后Java堆中有着指向方法区的引用。

    所以,如果我们移动了 Java 堆中的对象,那么Java栈中的引用就得进行变动。

    像我们之前说的 标记-清除 算法就没这个问题,因为它不移动存活对象,只是单纯删除不用的对象。

    回到我们的 标记-复制算法,如果每次复制的时候,有大量的对象需要复制,那么时间开销就很大了。

    标记-整理(标记-压缩)

    现在看下标记-整理算法,注意看上面的部分,当我们标记出存活对象的时候,我们就对他们进行移动整理,进而避免了垃圾碎片。

    但也就像我们之前说的,因为涉及到存活对象的移动,所以也有比较大的时间开销。

    分代收集算法

    我们注意到上面三种算法,各自都有其缺陷和擅长的地方。

    • 标记-清除适合少量垃圾存在的时候
    • 标记-复制适合有大量垃圾存在的时候
    • 垃圾-整理算法适合少量垃圾的时候

    于是,因地制宜,按照对象的不同生命周期,提出了分代收集算法。

    • 弱分代假说:绝大多数对象都是朝生夕灭的
    • 强分代假说:熬过多次垃圾回收过程的对象,就越难消亡

    于是,根据这种特点,就把内存大致分为老年代、年轻代。

    年轻代中的对象,绝大多数很快就会消亡,所以存在大量的垃圾,可以采用标记-复制算法

    老年代中的对象,很少对象会消亡,所以存在少量垃圾,可以采用标记-清除,和标记整理算法。

    老年代 和 年轻代的更多细节,我们下次再说。

  • 相关阅读:
    UIautomator Python测试
    selenium提供了三种模式的断言:assert,verify,waitfor
    编译标志
    模块级函数
    执行匹配
    反斜杠
    正则表达式
    重复
    字符匹配
    贪婪 vs 不贪婪
  • 原文地址:https://www.cnblogs.com/zhouzhiyao/p/13172306.html
Copyright © 2011-2022 走看看