资讯专栏INFORMATION COLUMN

GC_4_GC复制算法

elarity / 1695人阅读

摘要:什么是复制算法复制算法是利用空间进行分配的。另一方面,因为复制算法只搜索并复制活动对象,所以跟一般的标记清除算法相比,它能在短时间内完成,也就是说其吞吐量优秀。在复制算法中,每次运行时都会执行压缩。

4 GC复制算法

  Copying GC是Marvin L.Minsky在1963年研究出来的算法。就是指把某个空间里的活动对象复制到其它空间,把原空间里的所有对象都回收掉。在此,将复制活动对象的原空间称为From空间,将粘贴活动对象的新空间称为To空间。

4.1 什么是GC复制算法
  GC复制算法是利用From空间进行分配的。当From空间被完全占满时,GC会将活动对象全部复制到To空间。当复制完成后,该算法会把From空间和To空间互换,GC也就结束了。From空间和To空间大小必须一致。这是为了保证能把From空间中的所有活动对象都收纳到

4.1.1 执行过程
假设目前堆里的配置如下。
  

执行GC。首先是从根直接引用的对象B和G,B先被复制到了To空间。

将B被复制后生成的对象称为B’。在From空间中B已经被打上了复制完成标签。但是,这里只把B’复制了过来,它的子对象A还在From空间里,下面把A复制到To空间里。
  

这次才是真正意义上复制了B。因为A没有子对象,所以对A的复制就完成了。

接下来,要和复制B一样从根引用复制G,以及其子对象E。虽然B也是G的子对象,不过因为已经复制完B了,所以只要把从G执行B的指针转换到B’上。

最后,只要把From空间和To空间互换,GC就结束了。

对象C、D、F因为没法从根查找,所以会被回收。这里程序是以B、A、G、E的顺序搜索对象的,使用的是深度优先搜索。

4.2 优点
4.2.1 优秀的吞吐量

GC标记-清除算法消耗的吞吐量是搜索活动对象(标记阶段)所花费的时间和搜索整体堆(清除阶段)所花费的时间之和。

另一方面,因为GC复制算法只搜索并复制活动对象,所以跟一般的GC标记-清除算法相比,它能在短时间内完成GC,也就是说其吞吐量优秀。

尤其是堆越大,差距越明显。GC标记-清除算法在清除阶段所花费的时间会不断增加,但GC复制算法就不会。因为它消耗的时间是与活动对象的数量成比例的。

4.2.2 可实现高速分配

GC复制算法不使用空闲链表,因为分块是一块连续的内存空间。因此,调查这个分块的大小,只要这个分块大小不小于所申请的大小,那么移动指针就可以进行分配了。

比起GC标记-清除算法和引用计数算法等使用空闲链表的分配,GC复制算法明显快得多。使用空闲链表是为了找到满足要求的分块,需要遍历空闲链表,最坏的情况是我们不得不从空闲链表中取出最后一个分块,这样就用了大量时间把所有分块都调查一遍。

4.2.3 不会发生碎片化

基于算法性质,活动对象被集中安排在From空间的开头。像这样把对象重新集中,放在堆中一端的行为叫作压缩。在GC复制算法中,每次运行GC时都会执行压缩。

因此GC算法有个非常优秀的特点,就是不会发生碎片化,也就是说可以安排分块允许范围内大小的对象。

另一方面,在GC标记-清除算法等GC算法中,一旦安排了对象,原则上就不能再移动它了,所以会多多少少产生碎片化。

4.2.4 与缓存兼容

在GC复制算法中有引用关系的对象会被安排在堆里离彼此较近的位置。B’引用A’,G’引用E’的顺序排列。这种情况有一个优点,那就是mutator执行速度极快。很多CPU都通过缓存来来高速读取位置较近的对象。这也是借助压缩来完成的,通过压缩来把有引用关系的对象安排在堆中较近的位置。

4.3 缺点
4.3.1 堆使用率低下

GC复制算法把堆分成二等分,通常只能利用其中一半来安排对象。也就是说只有一半堆能被使用,相比其他能使用整个堆的GC算法而言,这是GC复制算法的一个重大缺陷。

4.3.2 不兼容保守式GC算法

GC标记-清除算法有着跟保守式GC算法相兼容的优点。因为GC标记-清除算法不用移动对象。

另一方面,GC复制算法必须移动对象重写指针,所以有着跟保守式GC算法不相容的性质。虽然有限制条件,GC复制算法和保守式GC算法可以进行组合。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71535.html

相关文章

  • 【前端进阶之路】内存基本知识

    摘要:在运行脚本时,需要显示的指定对象。大对象区每一个区域都是由一组内存页构成的。这里是唯一拥有执行权限的内存区。换句话说,是该对象被之后所能回收到内存的总和。一旦活跃对象已被移出,则在旧的半空间中剩下的任何死亡对象被丢弃。 内存管理 本文以V8为背景 对之前的文章进行重新编辑,内容做了很多的调整,使其具有逻辑更加紧凑,内容更加全面。 1. 基础概念 1.1 生命周期 不管什么程序语言,内存...

    Simon_Zhou 评论0 收藏0
  • Java堆内存分配与回收策略

    摘要:主要在堆上分配内存,而堆又分为新生代和老年代两个部分,新生代又再分为区和区两部分,本文根据堆的划分,描述的内存分配策略。 java主要在堆上分配内存,而Java堆又分为新生代(YoungGen)和老年代(OldGen)两个部分,新生代又再分为Eden区和Survivor区两部分,本文根据java堆的划分,描述hotspot的内存分配策略。 showImg(https://segme...

    Steve_Wang_ 评论0 收藏0
  • 逐梦offer -- JVM篇

    摘要:的字节码解释器和编译器使用写屏障维护卡表。解释器每次执行更新引用的字节码时,都会执行一段写屏障,编译器在生成更新引用的代码后,也会生成一段写屏障。 4. JVM 4.1 GC 1. 垃圾收集 基础 : 可达性分析算法 GC ROOTS 复制算法 标记清除 标记整理 分代收集 -- 1. 新生代 ; 2.3 老年代注: Oop Map -- 安全点 -- 安全区 以下部分内容 来自 ...

    greatwhole 评论0 收藏0
  • JAVA GC垃圾回收(及一次内存泄漏处理)

    摘要:垃圾回收及一次内存泄漏处理内存分布上图展示了的架构图,本篇我们主要关注,运行时数据区。但是垃圾回收并不能百分百保证不会出现内存泄漏,所以了解垃圾回收,对于我们遇到内存泄漏时能更加清晰的分析原因,也能帮助我们写出更加安全,可靠的程序。 [toc] JAVA GC垃圾回收(及一次内存泄漏处理) showImg(https://segmentfault.com/img/remote/1460...

    RaoMeng 评论0 收藏0

发表评论

0条评论

elarity

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<