1) 标记/清除算法是怎么来的?

我们在程序运行期间如果想进行垃圾回收,就必须让GC线程与程序当中的线程互相配合,才能在不影响程序运行的前提下,顺利的将垃圾进行回收。

为了达到这个目的,标记/清除算法就应运而生了。

2)标记/清除算法的过程

它的做法是当堆中的有效内存空间(available memory)被耗尽的时候,就会让整个程序stop the world,然后进行两项工作,第一是标记,第二是清除

标记: 标记的过程其实就是,遍历所有的GC Roots,然后将所有的 GC Roots可达的对象标记为存活的对象。

清除: 清楚的过程将遍历堆中所有的对象中没有标记的对象全部清除掉

当程序运行期间,若可以使用的内存被耗尽的时候,GC线程就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没有被标记的对象全部清除掉,接下来便让程序恢复运行

3)为什么要stop the world

这个其实也不难理解,举个最简单的例子,假设我们的程序与GC线程是一起运行的,各位试想这样一种场景。

假设我们刚标记完的那个对象,暂且记为A,结果此时在程序当中又new了一个新对象B,且A对象可以到达B对象。但是由于此时A对象已经标记结束,B对象此时的标记位依然是0,因为它错过了标记阶段。因此当接下来轮到清除阶段的时候,新对象B将会被苦逼的清除掉。如此一来,不难想象结果,GC线程将会导致程序无法正常工作。

上面的结果当然令人无法接受,我们刚new了一个对象,结果经过一次GC,忽然变成null了,这还怎么玩?

4)标记/清理算法的缺点

1、首先,它的缺点就是效率比较低(递归与全堆对象遍历),而且在进行GC的时候,需要停止应用程序,这会导致用户体验非常差劲,尤其对于交互式的应用程序来说简直是无法接受。试想一下,如果你玩一个网站,这个网站一个小时就挂五分钟,你还玩吗?

2、第二点主要的缺点,则是这种方式清理出来的空闲内存是不连续的,这点不难理解,我们的死亡对象都是随即的出现在内存的各个角落的,现在把它们清除之后,内存的布局自然会乱七八糟。而为了应付这一点,JVM就不得不维持一个内存的空闲列表,这又是一种开销。而且在分配数组对象的时候,寻找连续的内存空间会不太好找。

看完它的缺点估计有的猿友要忍不住吐糟了,“这么说这个算法根本没法用嘛,那LZ还介绍这么个玩意干什么。”

猿友们莫要着急,一个算法有缺点,高人们自然会想尽办法去完善它的。而接下来我们要介绍的两种算法,皆是在标记/清除算法的基础上优化而产生的。

学习并转载自 https://www.cnblogs.com/Leo_wl/p/3269590.html

最新文章

  1. 小结一下:javascript 金额计算
  2. 使用 jquery 获取当前时间的方法
  3. 面试问题整理笔记系列 一 Java线程类
  4. C#语句
  5. sql 简单事务例子
  6. C++的STL在C#中的应用
  7. MongoDB Shell
  8. c++ timer基于win消息队列
  9. java源码剖析: 对象内存布局、JVM锁以及优化
  10. SAS中的剔除空格函数
  11. 如何使用FluentMigrator进行数据库迁移
  12. 一起学Android之Dialog
  13. window7安装python的xgboost库方法
  14. python 结巴分词简介以及操作
  15. mysql计算排名 转
  16. nginx多域名同IP同80端口配置
  17. Cognos访问权限之让拒绝更友善
  18. Exchange Database Status(Copy Status ,Content Index State,QueueLength,Move Status...)
  19. 转载SQL_trace 和10046使用
  20. Sublime Text 2 入门与总结

热门文章

  1. Microsoft Word、Excel、PowerPoint转Pdf
  2. DBA面试题及解答
  3. 怎样使用DWZ?
  4. SecureCRT 常用技巧
  5. NUC972 MDK NON-OS
  6. 数据库为什么要用B+树结构--MySQL索引结构的实现(转)
  7. 分布式项目中 linux 服务器 部署jar 应用脚本 deploy.sh
  8. Django学习笔记第十二篇--关于自定义数据库字段数据类型
  9. iOS UILabel两侧加阴影
  10. 详说 CSS 清除浮动