编程高手必学的内存知识
海纳
华为编译器高级专家,原 Huawei JDK 团队负责人
20674 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 33 讲
编程高手必学的内存知识
15
15
1.0x
00:00/00:00
登录|注册

20 | Scavenge:基于copy的垃圾回收算法

你好,我是海纳。
上一节课中,我们讲到 GC 算法大致可以分为两大类:引用计数法和基于可达性分析的算法。在基于可达性分析的 GC 算法中,最基础、最重要的一类算法是基于 copy 的 GC 算法(后面简称 copy 算法)。
Copy 算法是最简单实用的一种模型,也是我们学习 GC 算法的基础。而且,它被广泛地使用在各类语言虚拟机中,例如 JVM 中的 Scavenge 算法就是以它为基础的改良版本。所以,掌握 copy 算法对我们后面的学习是至关重要的。
这一节课,我们就从 copy 算法的基本原理开始讲起,再逐步拓展到 GC 算法的具体实现。这些知识将帮助你对 JVM 中 Scavenge 的实现有深入的理解,并且让你正确地掌握 Scavenge GC 算法的参数调优。

最简单的 copy 算法

基于 copy 的 GC 算法最早是在 1963 年,由 Marvin Minsky 提出来的。这个算法的基本思想是把某个空间里的活跃对象复制到其他空间,把原来的空间全部清空,这就相当于是把活跃的对象从一个空间搬到新的空间。因为这种复制具有方向性,所以我们把原空间称为 From 空间,把新的目标空间称为 To 空间。
分配新的对象都是在 From 空间中,所以 From 空间也被称为分配空间(Allocation Space),而 To 空间则相应地被称为幸存者空间(Survivor Sapce)。在 JVM 代码中,这两套命名方式都会出现,所以搞清楚这点比较有好处。我们这节课为了强调拷贝进行的方向,选择使用 From 空间和 To 空间来分别指代两个空间,而尽量不使用分配空间和幸存者空间的说法。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

基于copy的垃圾回收算法Scavenge是本文的重点内容。该算法通过将堆空间分为From空间和To空间,将活跃对象从From空间复制到To空间来进行垃圾回收。文章详细介绍了copy算法的实现过程,包括对象的内存布局、垃圾回收方法以及深度优先遍历和广度优先遍历两种算法用于图的遍历。在实现复制过程中,文章提到了解决重复访问对象和对象引用修改的问题,引入了forwarding指针的概念。此外,文章还介绍了Scavenge算法是简单copy算法的一种改进,通过将To空间分成S0和S1两部分,提升了空间的总体利用率。文章还提到了深度优先搜索和广度优先搜索两种算法的优缺点,以及JDK6以前和JDK8以后JVM使用的不同GC算法。总体来看,基于Copy的GC算法有以下特点:对象之间紧密排列,中间没有空隙,分配内存效率高,回收效率取决于存活对象的多少,内存利用率并不高,需要搬移对象,因此需要业务线程暂停。文章内容深入浅出,适合想要了解垃圾回收算法的读者阅读。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编程高手必学的内存知识》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(6)

  • 最新
  • 精选
  • 费城的二鹏
    通过信号量通知,然后在编译生成的代码中插入检查点。用于检查信号量,判断是否需要停顿。

    作者回复: 检查点是对的。这种检查点的机制和信号有点像,都是业务线程要主动去处理。

    2021-12-13
    2
  • 王建新
    请问,最后的问题,线程的停止时sleep吗

    作者回复: 线程确实是休眠,但我这里问的问题是线程什么时候休眠,怎么样可以使得所有业务线程停下来呢?

    2021-12-24
  • 李二木
    safepoint?

    作者回复: 是的。但你知道safepoint是怎么发生作用的吗?

    2021-12-13
  • 送过快递的码农
    老师,关于这个我有两个疑问 1,this是不是就是对象头部最顶端的内存地址 2,我们在复制算法执行完之后,对象地址发生改变。我们业务线程里面的栈里面的引用,啥时候变更的呢?比如Object obj = new Object(); 这个被多个线程栈里面都有这个地址,这个值更新的问题,是标志的时候,通过记一个列表,然后统一更新的么?这个感觉也挺复杂的

    作者回复: 1. this是Java层面的概念。其实我们不应该去管它的地址是什么。但如果你非要使用Unsafe对它进行访问,那么,是的,它指向的是对象头部的地址。 2. 栈上的指针也是在对象拷贝阶段更新的呀。这和普通对象有什么不同呢?都是一个二维指针罢了。并不复杂,它没有什么特别之处。非要说有的话,那就是编译器要操心栈上哪些地方是引用,哪些地方是引用。这就是栈的OopMap,这个由编译器操心。内存管理器是不必操心的。

    2021-12-13
  • 约书亚
    看过中村成洋那本《垃圾回收的算法与实现》,这节课的伪代码还是挺熟悉的。 我比较好奇的是,在栈帧的那部分根,是怎么统计出来的,是要在生成机器码的时候加入一个操作,每在栈上或者是寄存器里保存一个值(就是对象的引用)时,同时还要操作某个数据结构来记录一下么?而且在栈帧销毁之前,还要从这个数据结构中将对应引用的数据删除
    2023-09-09归属地:天津
  • 王建新
    “使用 scanned 指针将非递归的广度优先遍历所需的队列,巧妙地隐藏在了 To 空间中” ---这个不是特别理解,有人能帮忙解答下吗
    2021-12-24
    3
收起评论
显示
设置
留言
6
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部