概述

还记得标记清除复制算法的问题么? 堆使用效率低和碎片化问题. 那么有没有能够利用整个堆, 有没有内存碎片化问题的算法呢? 这就是标记压缩算法了.

简单来说, 标记压缩算法就是将堆中的所有活动对象整体向左移, 将对象间的空隙消除.

在GC执行前的内存:

GC执行后的内存:

恩, 就是这么个意思.

实现

如何实现上面的操作呢? 首先, 要将所有活动对象标记出来. 这是标记阶段, 跳过了, 跟标记清除一样操作就行. (这里每个对象都有一个mark属性, true为活动对象)

标记完了, 那就剩下压缩操作了. 如何进行呢?

  1. 遍历堆, 将所有活动对象挪到左边. 但是, 后面有对象引用了前边的对象, 你就找不到新的指针了, 因为那块地址很可能已经被覆盖了.

  2. ....

最后想了想, 还是得老老实实地三步走:

  1. 遍历堆, 将所有对象通过计算得到新的地址并保存

  2. 遍历堆, 将所有子对象的地址更新为新的地址, 同时更新根集合中的指针.

  3. 遍历堆, 将对象集体迁移. 指针的问题都解决了, 可以将对象搬到新家了.

步骤一: 计算所有对象的新地址

// HEAP_START 是堆的开始位置, HEAP_END 是堆得结束位置
obj = HEAP_START
newAddr = HEAP_START
// 遍历所有活动对象
while(obj < HEAP_END){// 非活动对象, 跳过if(obj.mark != true){obj += obj.size;continue;}// 记录新的地址obj.newAddr = newAddrnewAddr += obj.size// 继续遍历obj += obj.size
}

这遍完后, 所有活动对象都保存了自己的新地址, 然后就可以将所有指针的地址进行更新了.

步骤二: 更新所有指针

// 更新根集合中的指针
for(obj in roots){obj = obj.newAddr
}
/*
更新所有活动对象的指针
当然, 这里也可以修改为遍历所有活动对象, 并将指针进行更新. 但是会出现各种重复处理、指针覆盖等问题, 就直接遍历堆了.
*/
obj = HEAP_START
while(obj < HEAP_END){if(obj.mark != true){obj += obj.size;continue;}// 更新子对象for(child in children){child = child.newAddr}obj += obj.size
}

至此, 所有指针都已经更新完毕, 但是, 对象还没有移动. 只剩下最后一步了, 将对象按照步骤一的规律, 向左排排坐就好啦.

步骤三: 迁移对象

obj = newAddr = HEAP_START
while(obj < HEAP_END){if(obj.mark != true) {obj += obj.size;continue;}// 将obj的数据复制到newAddr处copyData(newAddr, obj, obj.size);// 清空数据, 为下一次GC做准本newAddr.mark = false;newAddr.newAddr = null;// 遍历下一个对象obj += obj.sizenewAddr += obj.size
}

至此, 实现基本完成. 创建对象分配内存的操作与复制算法一样. 这个算法简直是融合了标记清除复制算法的优点, 解决了他们的问题, 不光堆的使用效率变高了, 而且也没有内存碎片的问题了. 但是, 就是, 只不过要对堆进行三次遍历而已. 不过没关系啦, 毕竟有失才有得嘛. 不过是时间换空间了.

而这, 也是标记压缩算法最大的问题了, 执行时间太久了, 标记清除对堆进行一次遍历, 而标记压缩要进行三次. 三倍的时间. 可想而知.

不过也有伟人说了, 算法没有好不好, 只有是否适合. 这几种可达性的算法各有优劣吧.

标记压缩的衍生

Two-Finger算法

将堆的遍历次数减少到两次.

如上图所示, 在第一次遍历的时候, 指针1从前向后寻找空闲地址, 指针2从后向前寻找活动对象, 找到后在原地址中记录新地址, 并将对象进行复制.

第二次遍历就可以将所有对象中的指针进行更新了.

你也发现了, 这个算法如果不想发生内存碎片化, 那就只能令每个对象的空间都是相同的. 而事实上也确实是这样. 强行规定每个对象都占用相同大小的空间, 我不知道这算法有什么应用场景. (原谅我的无知)

其他

还有一些其他的表格算法lmmixGC算法等, 因为这两个我看的似懂非懂, 就不细说了.


标记压缩算法差不多就这么些. 告辞~~~

GC算法-标记压缩算法相关推荐

  1. 【Android 内存优化】垃圾回收算法 ( 内存优化总结 | 常见的内存泄漏场景 | GC 算法 | 标记清除算法 | 复制算法 | 标记压缩算法 )

    文章目录 一. 内存优化总结 二. 常见的内存泄漏场景 三. 内存回收算法 四. 标记-清除算法 ( mark-sweep ) 五. 复制算法 六. 标记-压缩算法 一. 内存优化总结 内存泄漏原理 ...

  2. GC算法 (标记清除、复制、标记整理、 分代收集) 、 新生代 老年代

    一.标记-清除算法(Mark-Sweep)   1标记阶段:首先通过根节点,标记所有从根节点开始的可达对象.未被标记的对象就是未被引用的垃圾对象 2清除阶段:清除所有未被标记的对象. 不足:1效率问题 ...

  3. GC算法-标记清除算法

    概述 标记清除算法, 描述起来很简单, 从名字上就能看出, 分为两个阶段: 标记阶段: 遍历所有对象, 将活动对象都打上标记 清除阶段: 遍历堆, 将没有标记的对象释放掉. 介绍完毕, 本文结束. 开 ...

  4. 【超详细】JVM之内存管理和GC算法

    一:JVM架构之class字节码 JVM整体架构(HotSpot JVM) java启动命令 java程序的允许需要使用java命令来负责启动 java启动的时候需要找到入口main方法 java启动 ...

  5. JVM(三)GC垃圾回收以及四种GC算法

    JVM(三) 学习视频链接,以示尊重:https://www.bilibili.com/video/BV1iJ411d7jS?p=4 图片来源:https://blog.csdn.net/weixin ...

  6. JVM 知识梳理 (二) GC算法

    文章目录 一.前言 二.判定哪些对象需要被GC 引用计数法Reference Count 可达性算法(引用链法Tracing) 三.GC算法 标记-清除 标记-压缩 复制算法 总结 分代收集 补充:H ...

  7. JVM入门(位置、体系结构、类加载器、双亲委派机制、沙箱安全机制、Native、PC寄存器、方法区、堆(新生区{伊甸园区、幸存区}、养老区、永久区)、OOM、GC算法、JMM)

    目录 一.JVM的位置 二.JVM的体系结构 三.类加载器 1.类加载器举例 2. JVM中提供了三层的ClassLoader 3. 双亲委派机制(重要) 3.1 工作原理 3.2.优点 四.沙箱安全 ...

  8. 26 Java GC算法 垃圾收集器、标记 -清除算法、复制算法、标记-压缩算法、分代收集算法

    26.Java GC算法 垃圾收集器 1.1.1标记 -清除算法 1.1.2复制算法 1.1.3标记-压缩算法 1.1.4分代收集算法 26.Java GC算法 垃圾收集器 概述 垃圾收集 Garba ...

  9. 垃圾回收机制之标记压缩算法与分代算法

    标记清除算法其实和标记压缩算法其实非常相同,标记压缩算法是在标记清除算法之上,解决内存碎片化的问题,就是删不干净的问题,因为他的整个排序不是很好,标记压缩,有的地方叫做标记整理,都是一个意思,标记压缩 ...

最新文章

  1. Python基础01-Python环境搭建与HelloWorld
  2. Qt 之 Qt/Qt Lite 自编译详解(VS/MinGW/...)
  3. 04/28/2010 类,对象,变量
  4. python脚本自动化盲注_三、基于报错型注入和sql盲注的自动化实现
  5. VS2019调试查看变量_单片机编程软件一点通,IAR单片机编程软件工程调试方法
  6. 用FileZilla搭建的Ftp其他电脑无法访问的问题
  7. 数据结构-约瑟夫问题课后作业
  8. linux SO文件
  9. 远在美国的凤姐为何选择回国理財?
  10. Oracle 根据业务创建新的用户
  11. 那些年使用Android studio遇到的问题
  12. 服务器每个月维护要1000元,5月24日服务器例行维护公告(已完成)
  13. SpringBoot-短信发送
  14. spanning tree protocol
  15. c语言过磅系统,衡安无人值守地磅称重系统过磅流程
  16. 使用Python进行12306抢票
  17. RFC868--时间协议客户机与服务器的实现
  18. 计算机表格中平方根符在哪插入,开方符号-平方根符号怎么打?平方根符号在word和Excel中怎么打?上面 爱问知识人...
  19. R语言的修仙之道--R语言之后天境界
  20. matlab绘制垂线(x轴或y轴)

热门文章

  1. Modbus协议栈应用实例之三:Modbus TCP客户端应用
  2. 计算机PPT03,南京大学计算机网络课件03.ppt
  3. 如何计算实际物理地址?
  4. 如何做推荐系统 java_Java程序员的日常——SpringMVC+Mybatis开发流程、推荐系统
  5. 一元三次方程重根判别式_如何求一元三次方程
  6. python删除txt指定内容_python删除文件中指定内容
  7. python 3.7.732位安装步骤_Python3.7安装pyaudio教程解析
  8. mysql操作json优点和缺点_SQL-mysql操作json
  9. db2 sql 判断select是否为空_学会复杂一点的SQL语句:Oracle DDL和DML
  10. qt执行命令行失败_QT缺少 qtcore4.dll,debug下运行不成功