• 《垃圾回收的算法与实现》——GC标记-清除算法


    基本算法

    • 标记-清除算法由 标记阶段清除阶段 构成。
    • 标记即将所有活动的对象打上标记。
    • 清除即将那些没有标记的对象进行回收。

    标记与清除

    • 遍历GC root引用,递归标记(设置对象头中的标志位)对象。
    • 标记时如果标志位表示已经标记过则可以跳过。
    • 遍历对象有深度优先与广度优先两种算法,其搜索的步骤数一致,而深度优先的内存使用量更小,因此一般使用深度优先。
    • 清除阶段将再次遍历堆,未标记的对象加入到空闲链表中,标记的对象则去除标记。

    分配与合并

    • 分配指mutator(Application)申请分块时获取内存块的过程。
    • 分配即通过搜索空闲链表,找到一个大小合适的块。分配测量有如下:
      • First-fit,找到第一个大于要求大小的块即返回。
      • Best-fit,找到比要求大小大的最小块。
      • Worst-fit,找出最大的块将其分割成要求大小块和剩余的,一般不使用(容易产生碎片)
    • 对于内存中连续的垃圾可以对其进行合并,减少碎片。

    优缺点

    优点

    1. 算法实现简单。
    2. 与保守式GC算法兼容(对象不能被移动)。

    缺点

    1. 碎片化。
    2. 分配速度慢,每次分配需要遍历空闲链表。
    3. 与写时复制(copy-on-write)冲突,因为做GC时需要将对象头进行标记,这将导致大量的数据发生复制。
    4. STW(Stop-The-World)长,两个阶段均要遍历整个堆。

    改进

    多个空闲链表

    针对分配速度慢

    • 根据块的大小建立不同的空闲链表,相同大小的块链接到相同链表中。
    • 由于对于大块的申请比较少,因此主要针对小块建立链表,对于大块的可以都在同一个链表中,如大于2-100的分别建立各自大小的链表而大于100的都写入一个大块链表。

    BiBOP

    针对碎片化

    • 原理:将大小相近的对象整理成固定大小的块进行管理。
    • 把堆分割成固定大小的块,让每个块只能配置同样大小的对象。
    • 但是并不能很好的消除碎片化,如果对堆的分隔没控制好反而可能导致堆的利用率。

    位图标记

    针对写时复制

    • 由于GC过程需要修改对象中属性导致写时复制不兼容,因此指收集各个对象的标志位并表格化。
    • 将堆中的对象与位图对应上,而后通过位图的标志代表堆中对象的标志。
    • 优点:
      • 兼容写时复制
      • 清除阶段可以快速的去除标记。

    延迟清除法

    针对STW过长

    • 延迟清除法(Lazy-Sweep)是缩减清除操作而导致的mutator STW的方法。
    • 标记结束后不做清除操作而是在分配操作中进行。
    • 在分配时,从上次遍历结束的地方开始使用First-fit查找块,如果找不到返回NULL,此时进行标记阶段而后再次进行First-fit查找。还找不到则分配失败。
  • 相关阅读:
    团队项目 NABCD介绍
    java web项目通过外网ip访问
    第七周总结
    全球疫情可视化展示
    第六周总结
    软工小队——团队介绍
    Android端疫情数据统计与现实——Android连接Mysql
    android SDK SDK Manager.exe 无法打开,一闪而过最终解决办法 (转)
    第五周总结
    Java代码编写规范(转)
  • 原文地址:https://www.cnblogs.com/suolu/p/6649211.html
Copyright © 2020-2023  润新知