摘要:什么是复制算法复制算法是利用空间进行分配的。另一方面,因为复制算法只搜索并复制活动对象,所以跟一般的标记清除算法相比,它能在短时间内完成,也就是说其吞吐量优秀。在复制算法中,每次运行时都会执行压缩。
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 生命周期 不管什么程序语言,内存...
摘要:主要在堆上分配内存,而堆又分为新生代和老年代两个部分,新生代又再分为区和区两部分,本文根据堆的划分,描述的内存分配策略。 java主要在堆上分配内存,而Java堆又分为新生代(YoungGen)和老年代(OldGen)两个部分,新生代又再分为Eden区和Survivor区两部分,本文根据java堆的划分,描述hotspot的内存分配策略。 showImg(https://segme...
摘要:的字节码解释器和编译器使用写屏障维护卡表。解释器每次执行更新引用的字节码时,都会执行一段写屏障,编译器在生成更新引用的代码后,也会生成一段写屏障。 4. JVM 4.1 GC 1. 垃圾收集 基础 : 可达性分析算法 GC ROOTS 复制算法 标记清除 标记整理 分代收集 -- 1. 新生代 ; 2.3 老年代注: Oop Map -- 安全点 -- 安全区 以下部分内容 来自 ...
摘要:垃圾回收及一次内存泄漏处理内存分布上图展示了的架构图,本篇我们主要关注,运行时数据区。但是垃圾回收并不能百分百保证不会出现内存泄漏,所以了解垃圾回收,对于我们遇到内存泄漏时能更加清晰的分析原因,也能帮助我们写出更加安全,可靠的程序。 [toc] JAVA GC垃圾回收(及一次内存泄漏处理) showImg(https://segmentfault.com/img/remote/1460...
阅读 583·2021-10-08 10:20
阅读 1465·2021-09-23 11:22
阅读 3200·2019-08-30 15:55
阅读 1458·2019-08-28 18:25
阅读 1833·2019-08-28 18:14
阅读 1211·2019-08-26 11:37
阅读 2878·2019-08-26 10:18
阅读 2406·2019-08-23 18:39