博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
标记-清除算法,复制算法,标记-整理算法和分代算法
阅读量:5888 次
发布时间:2019-06-19

本文共 1777 字,大约阅读时间需要 5 分钟。

  最近笔者在学习JVM相关的知识,故写作此文来分享一下本人了解的一些垃圾回收算法。

  

  标记回收算法

 


  最基础的垃圾回收算法就是“标记-回收”算法(Mark-Sweep)算法,这是其它所有垃圾回收算法的基础,相当于内功,其它算法都是根据内功来发挥的外功。顾名思义,本算法需要先标记出所有需要回收的对象,待标记完成后,再统一回收所有被标记的对象。它的缺点很明显,首先是效率太低,标记和回收这两个过程的效率都不算太高;其次,因为需要回收的对象不一定是连续的(实际上往往都不是),因此会产生很多内存碎片,一旦需要分配一个较大的空间给某个新对象的时候,很可能就会因为没有足够的连续内存,从而再运行一次gc机制,其实也是影响程序的运行效率。

  画一张图帮助理解一下对象占用内存的情况。

 

  复制算法


  CopyingGC算法是Marvin L.Minsky在1963年研究出来的算法,用来改进标记-回收算法。简单的说,就是把内存划分为两块(两块大小不一定要相等,事实上,也不建议相等,下面会详细说明),每次只使用其中的一块,当内存空间被占用完以后,就把尚在存活的对象存到另外的半区,再将当前半区已使用的内存空间一次清除掉。这样在分配内存时就不用考虑空间碎片,也不用使用空闲链表,避免了这类麻烦问题,只用移动堆顶指针,按顺序分配内存即可,有效提高了效率。

  现代的商业虚拟机大多数都是采用了复制算法,只不过不是狭义上的复制算法而已,而是采用了多空间复制算法,因为传统的复制算法会划出整个半区作为TO空间,这样做的成本未免太高了。IBM公司的研究表明,新生代内的大部分对象都是朝生夕死的,所以没有必要分配这么多内存空间去复制,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor空间,HotSpot虚拟机最初使用的就是这种内存分配方式。当需要回收内存的时候,就把Eden和Survivor中还存活着的对象一次性地复制到另一块Survivor上,最后清理掉Eden和Survior,HotSpot默认的Eden和Survivor比例是8:1:1,就是说,每次能使用90%的内存容量。当然,也可能会出现剩余10%的Survivor空间不够复制原有存活对象的情况,那就需要依赖其它内存(这里指老年代)进行分配担保(Handle Promotion)。通过分配担保机制,这些对象会直接进入老年代。实际上,说的再通俗一点,就是将Eden和一块有内容的Survivor上存活的对象,复制到没有内容的Survivor上,然后有内容的Survivor变成没有内容的Survivor,没有内容的Survivor变成有内容的Survivor。

 

  标记-整理算法

 


  虽然说复制算法效率很高,但这是在对象死亡很快的情况下,如果对象存活率较高,那就需要进行很多的复制操作,很影响效率。何况,还需要额外的空间进行分配担保,因此,老年代不能采用这种算法,老年代采用的是复制-整理算法(Mark-Compact)。

  这种算法和标记-清除算法很像,唯一不同的是,当标记完成后,不是清理掉需要回收的对象,而是将所有存活的对象向一端移动,然后将边界以外的内存全部清理掉,这样可以有效避免空间碎片的产生。

 

  分代算法

 


  分代算法(Generational Collection),现代的虚拟机大都采用了这种gc回收算法,通过将内存根据存活时间的不同划分为不同代,来选择最合适的对象回收算法,一般来说是分为新生代和老年代。新生代的对象更新很快,朝生夕死,所以使用复制算法,老年代的对象存活率很高,所以采用标记/压缩算法。

 


  最后,总结一下在JVM里面所使用的GC回收算法。

      新生代串行收集/并行回收器:复制算法

      老年代串行收集/并行回收器:标记/压缩算法

      并行收集器:将串行收集器多线程化,回收策略和串行收集器一致,因此该收集器是新生代为复制算法,老年代为标记-压缩算法。

      CMS收集器:Concurrent Mark Sweep,从名字就可以看出来用的是标记清除算法

   

转载于:https://www.cnblogs.com/CNty/p/10917531.html

你可能感兴趣的文章
redhat安装opencv
查看>>
十进制与其他进制转换
查看>>
web端测试小知识
查看>>
8.30 牛客OI赛制测试赛1 F题 子序列
查看>>
.NET中<asp:MultiView>选项卡控件的用法
查看>>
为什么用bower 安装bootstrap而不用npm来安装?
查看>>
通过游戏来学习CSS的Flex布局
查看>>
Firefly加入OPEN AI LAB生态计划,推出AI开源主板
查看>>
递归函数实现方法
查看>>
[转]Windows7 64bit下配置Apache+PHP+MySQL
查看>>
CentOS6.5 下在Nginx中添加SSL证书以支持HTTPS协议访问
查看>>
给trac的ticket添加提交时字段验证
查看>>
nodejs安装-配置
查看>>
Node.js学习-1
查看>>
今天你的应用崩溃了么?
查看>>
项目中的*签到*小功能!
查看>>
iOS 获取cell.accessoryView自定义视图以及点击事件
查看>>
java 考试试题
查看>>
[caffe(一)]使用caffe训练mnist数据集
查看>>
闭包,装饰器
查看>>