《垃圾回收的算法与实现》——GC复制算法

https://www.cnblogs.com/suolu/p/6654236.html

基本概念

  • GC复制算法将堆分成From和To两个内存块,当From被占满时GC将From中的存活对象复制到To中,同时将From和To交换。
  • 通过递归遍历GC root(即采用深度优先)复制存活对象,对于已经复制过的标记其COPIED字段。
  • 复制过的对象将在From的对象的forwarding记录To中该对象地址,以便于其余引用了该对象的引用进行修改。
  • 分配对象时将先判断From中连续可用空间是否够用(复制算法不存在碎片),如果不够则进行一次GC,还不够则分配失败。

优缺点

优点

  1. 吞吐量大,只需要遍历一次From空间Sweep需要遍历两次,而且只复制存活的对象。
  2. 高速分配,不需要通过空闲链表直接在连续的内存上进行分配。
  3. 没有碎片。
  4. 与缓存兼容,复制存活对象时采用深度优先算法使相关联的对象都在附近。

缺点

  1. 堆的使用效率低,必须分配一个To,其不能分配对象。
  2. 不兼容保守式GC算法,需要移动对象。
  3. 递归调用,复制对象的深度优先算法是通过递归调用实现的,递归将消耗栈等资源。

改进

Cheney的GC复制算法

针对递归

  • 复制算法的To中增加scan指针,其指向To中已经复制过所有子对象位置。
  • 首先将GC root直接引用的对象复制到To中,而后通过scan指针的移动对后续存活对象进行复制。实现了广度优先搜索算法
  • 通过scan在To中的移动实现了一个隐式的FIFO队列。
  • 取消COPIED字段,通过forwarding字段是否指向To区间来判断该对象是否已被复制。
  • 优点在于取消了递归,缺点则是采用了广度优先算法使其与缓存不兼容。

近深度优先搜索方法

针对Cheney的复制算法中与缓存不兼容问题

  • page:堆分隔成一个个页面的数组;local_scanf:每个页中搜索用的指针作为元素的数组;major_scan:指向未搜索完的页面开头;free:分块开头;
  • 第一阶段从GC root中将其直接引用复制到第一个页中。
  • 而后对每个对象按照类似深度优先算法,区别在于其原始深度优先算法每层一次只搜索一个对象而该算法则将同一层一次搜索完 此处没懂,还有页占满的问题

多空间复制算法

针对堆利用率低

  • 将堆分成多份,每次取其中的两个分别作为From和To,其余则采用Mark-Sweep算法。
  • From总在To的右边的块中,每执行一次GC,From和To均向右移动一个块。
  • 在GC时先进行标记阶段,当存活对象处于From时执行copy,当处于其余块时执行mark。
  • 优点在于提高了堆的利用率,缺点则是引入了Mark-Sweep算法导致STW时间变长,分块得采用空闲链表

原文地址:https://www.cnblogs.com/0xcafedaddy/p/9750726.html

时间: 2024-10-05 13:36:50

《垃圾回收的算法与实现》——GC复制算法的相关文章

JVM_垃圾回收串行、并行、并发算法(总结)

一.串行 JDK1.5前的默认算法 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长 语法 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 示例图 测试代码 //-Xmx20m -Xms20m -Xmn2m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps byte[] b = null; for (int i = 0; i < 7; i++) { b = new byte

Java的垃圾回收和内存分配策略

本文是<深入理解Java虚拟机 JVM高级特性与最佳实践>的读书笔记 在介绍Java的垃圾回收方法之前,我们先来了解一下Java虚拟机在执行Java程序的过程中把它管理的内存划分为若干个不同的的数据区的什么? 1.Java运行时数据区的划分 如下图: 其中程序计数器,虚拟机栈,本地方法栈这3个区域的内存随线程而生,随线程而灭的,因此这几个区域的内存分配与回收都是有确定的,我们不需要考虑这几个区域的内存的分配与回收.而堆和方法区则不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分

JVM优化 垃圾回收 算法 垃圾收集器 GC日志可视化查看

今日内容了解什么是垃圾回收掌握垃圾会回收的常见算法学习串行.并行.并发.G1垃圾收集器学习GC日志的可视化查看 1.什么是垃圾回收?程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存 资源,最终将导致内存溢出,所以对内存资源的管理是非常重要了. 1.1.C/C++语言的垃圾回收在C/C++语言中,没有自动垃圾回收机制,是通过new关键字申请内存资源,通过delete 关键字释放内存资源.如果,程序员在某些位置没有写delete进行释放,那么申请的对象将一直占用内存资源,

JVM虚拟机垃圾回收(GC)算法及优缺点

一.什么是GC GC是jvm的垃圾回收,垃圾回收的规律和原则为: 次数上频繁收集新生区(Young) 次数上较少收集养老区(Old) 基本上不动永久区(Perm) 二.GC算法(分代收集算法) GC总共有四大算法,分别是: ①引用计数法 ②复制算法(Copying) ③标记清除(Mark-Sweep) ④标记压缩(Mark-Compact) ⑤标记清除压缩(Mark-Sweep-Compact) 1.1 引用计数法 1.2 复制算法(Copying) 复制算法主要用在新生代中. 1.2.1 复制

常用的垃圾回收算法

引用计数法 对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1. 只要A对象的引用计数器的值为0,则对象A就不可能再被使用. 实现也很简单,只需要为每个对象配备一个整型的计数器即可. 缺点: 1.无法处理循环引用的情况 2.引用计算器要求在每次引用产生和消除的时候,需要伴随一个加法操作和减法操作,对系统性能有一定影响. A引用了B,B又引用了A,因此A和B的引用计数器都不为0,但是系统中却 不存在任何第3个对象引用了A和B. 这种情况下,A和B是无

JVM垃圾回收算法 总结及汇总

先看一眼JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:jvm如何知道那些对象需要回收 ? 目前两种标识算法.三种回收算法.两种清除算法.三种收集器 引用计数法 每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收 这个可以用数据算法中的图形表示,对象A-对象B-对象C 都有引用,所以不会被回收,

JVM垃圾回收算法(最全)

JVM垃圾回收算法(最全) 下面是JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:jvm如何知道那些对象需要回收 ? 目前两种标识算法.三种回收算法.两种清除算法.三种收集器 引用计数法 每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收 这个可以用数据算法中的图形表示,对象A-对象B-对象C

JVM常见垃圾回收算法

jdk1.7.0_79 众所周知,Java是一门不用程序员手动管理内存的语言,全靠JVM自动管理内存,既然是自动管理,那必然有一个垃圾内存的回收机制或者回收算法.本文将介绍几种常见的垃圾回收(下文简称GC)算法. 在Java堆上分配一个内存给实例对象时,此时在虚拟机栈上引用型变量就会存放这个实例对象的起始地址. Object obj = new Object();  现在如果我们将变量赋值为null. obj = null; 此时可以看到Java堆上的实例对象无法再次引用它,那么它就是被GC的对

JVM 垃圾回收算法

在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是"垃圾". 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当计数器为0的时候,JVM就认为对象不再被使用,是"垃圾"了. 引用计数器实现简单,效率高:但是不能解决循环引用问问题(A对象引用B对象,B对象又引用A对象,但是A,B对象已不被任何其他对象引用),同时每次计数器的增加和减少都带来了很多额外的开销,所以在JDK1.1之后,