大家好,我是【小松与蘑菇】,即将毕业去深圳的大学生,致力于android,java相关领域,也对AI很感兴趣。正朝着写出通俗易懂而又有深度的文章而努力 前文地址 【GC算法几人知?】一、前置知识积累 今天来介绍GC复制算法,两个英语单词 From & To 所谓GC复制算法,就是将堆空间分成From和To空间,一边一半,所有新的对象都放在From空间,当From空间满的时候,就将非垃圾的对象搬移到To空间中,然后清空From空间,同时互换From和To的名字,这样又可以继续在From空间中进行新建对象了 思想很简单,但是以上方法有两个需要解决的问题 如何判定哪些是非垃圾对象,并找到 找到这些对象后如何复制他们到To空间 现在就让我们来一个一个解决吧 就是一个 可以看到,第一行表示标记To空间的首地址为free,然后通过根引用,找到所有被引用到的对象,他们就是非垃圾对象,通过 头里面含有两个信息: 比如说你搬家了,但是那些向你要债的人不知道你搬了,所以你可以在老家留下“我搬去火星”的字条,这样,那些要债的上门后看到字条,就知道要去火星找你了 现在来看看 可以看到,首先判定如果对象obj没有复制过,那么 到了商业互吹时间,从上面的步骤,我们可以看到他有如下优点 吞吐量高 分配速度快 没有碎片 兼容缓存(局部性好) 有一说一,这个算法的1,2,3优点已经注定了他时可以应用甚至是商用了,尽管他有以下缺点 然而,这种缺点稍稍思考就可以解决,From和To为什么非要1:1呢?可以是一个合适的比值吧 没错,这个方法将这两个缺点改正后再融合分代垃圾回收,将成为jdk8的垃圾回收方法,也是面试最常考点之一 ,将在下文详细解析
【GC算法几人知?】二、标记清除法 全解析
【GC算法几人知?】三、引用计数法,直抵GC本质的方法
如果你对这两个词在GC中的角色有印象的话,相信你一定了解过java的GC,因为在jdk中,也是划分了from空间和to空间,然后将里面的对象搬来搬去,这些都源自于Marvin L. Minsky在1963 年研究出来的GC复制算法,现在,让我们来深入了解一下吧概念

复制原理
copy()的事,看伪代码copying(){ $free=$to_start for( r: $roots) *r =copy(*r) swap($from_start,$to_start) } copy()函数将他们复制到To中,最后交换From和To,在看copy()函数之前,我们先看看对象obj的构造
copy()函数是如何复制的copy(obj){ if (obj.tag!=COPIED) copy_data($free,obj,obj.size) obj.tag=COPIED obj.forwarding=$free $free+=obj.size for(child:children(obj.forwarding)) *child=copy(*child) return obj.forwarding } copy_data()将真正的将其复制到新空间,就是把从obj首地址到其size的部分移动到$free处,当然此时$free需要向后移动obj的zie位置,为新的obj复制做准备
如图A’就是复制后的对象

然后forwarding记录$free地址,也就是移动后的新地址的首地址,

看到这我想你已经发现了,copy()代码最后的for循环想必就是解决A所指向的C,D的复制的吧
没错,copying()中已经确保了A是活动对象,那么A的子对象C,D就一定是活动对象了,那么,就递归的调用copy()函数即可,这样,A’,C’,D‘在To空间中还能保证是连续的哦copying()函数执行完毕

我们只需要堆每一个根在From中指向的对象都进行上述操作,就可以将所有对象和他们的关系都移动到To中,最后回收From空间,再交换To和From即可,所谓的交换,当然不是将双方的内容交换(那岂不是要再复制一遍??),是将From和To的标志互换即可优点
所谓吞吐量就是搜索活动对象的时间比上搜索堆时间,越高说明你的有效搜索占比越高,不难看出,我们都是从根开始,搜索的全部是活动对象,并没有浪费时间去搜索垃圾对象。这个优势在堆越大的场景下越明显
就是我们新建一个对象时,mutator需要申请多久才能完成,比如标记清除法时维护了一个空闲链表,使得找到一个合适的分块需要遍历链表,很花时间。但是在这里,我们都是从From空间中的$free处直接开辟的,标记清除法类似在停车场停车,需要一排一排看有没有合适的车位;而这里就像在大马路上停车,只要从最后一辆那里停就行
在将活动对象复制到To空间时,他们都是紧挨着的,然后清空From时全部清空,完全没有碎片的可能
在To空间中,父对象和子对象也是挨着的,参考上面的A’,C’,D’,所以利于缓存,局部性好缺点
这是最明显的,空间都被劈成两半了,一次永远只能用一半就得搬家
在对子对象进行复制时,使用了递归方法,可能导致栈溢出总结
既然递归会栈溢出,那么为什么不可以迭代呢?
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
官方软件产品操作指南 (170)