JVM-垃圾收集算法

2023-11-09

目录

1.分代收集理论

2.标记-清除算法

3.标记-复制算法

4.标记-整理算法


1.分代收集理论

       分代思想也很简单,就是根据对象的生命周期将内存划分,然后进行分区管理。 当前商业虚拟机的垃圾收集器大多数都遵循了“分代收集”(Generational Collection)的理论进行设计, 分代收集名为理论, 实质是一套符合大多数程序运行实际情况的经验法则, 它建立在两个分代假说之上:

  1. 弱分代假说(Weak Generational Hypothesis) : 绝大多数对象都是朝生夕灭的。
  2. 强分代假说(Strong Generational Hypothesis) : 熬过越多次垃圾收集过程的对象就越难以消亡。

        这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则: 收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数) 分配到不同的区域之中存储。 

        显而易见, 如果一个区域中大多数对象都是朝生夕灭, 难以熬过垃圾收集过程的话, 那么把它们集中放在一起, 每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象, 就能以较低代价回收到大量的空间; 如果剩下的都是难以消亡的对象, 那把它们集中放在一块, 虚拟机便可以使用较低的频率来回收这个区域, 这就同时兼顾了垃圾收集的时间开销和内存的空间有效利用。

        在Java堆划分出不同的区域之后, 垃圾收集器才可以每次只回收其中某一个或者某些部分的区域 ——因而才有了“Minor GC”“Major GC”“Full GC”这样的回收类型的划分; 也才能够针对不同的区域安 排与里面存储对象存亡特征相匹配的垃圾收集算法——因而发展出了“标记-复制算法”“标记-清除算法”“标记-整理算法”等针对性的垃圾收集算法。

他针对不同分代的类似名词, 为避免产生混淆, 在这里统一定义 :

部分收集(Partial GC) : 指目标不是完整收集整个Java堆的垃圾收集, 其中又分为: 

  1. 新生代收集(Minor GC/Young GC): 指目标只是新生代的垃圾收集。
  2. 老年代收集(Major GC/Old GC): 指目标只是老年代的垃圾收集,目前只有CMS收集器会有单独收集老年代的行为。
  3. 混合收集(Mixed GC): 指目标是收集整个新生代以及部分老年代的垃圾收集。 目前只有G1收集器会有这种行为。

整堆收集(Full GC) : 收集整个Java堆和方法区的垃圾收集

 

2.标记-清除算法

        算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象, 在标记完成后,统一回收掉所有被标记的对象, 也可以反过来, 标记存活的对象, 统一回 收所有未被标记的对象。

        标记过程就是对象是否属于垃圾的判定过程。 之所以说它是最基础的收集算法, 是因为后续的收集算法大多都是以标记-清除算法为基础, 对其缺点进行改进而得到的。

 

标记-清除算法有两个不足之处:

        第一个是执行效率不稳定, 如果Java堆中包含大量对象, 而且其中大部分是需要被回收的, 这时必须进行大量标记和清除的动作, 导致标记和清除两个过程的执行效率都随对象数量增长而降低;

        第二个是内存空间的碎片化问题, 标记、 清除之后会产生大量不连续的内存碎片, 空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找 到足够的连续内存而不得不提前触发另一次垃圾收集动作。 

 

3.标记-复制算法

        为了解决标记-清除算法面对大量可回收对象时执行效率低的问题, 1969年Fenichel提出了一种称为“半区复制”(Semispace Copying) 的垃圾收集算法, 它将可用内存按容量划分为大小相等的两块, 每次只使用其中的一块。 当这一块的内存用完了, 就将还存活着的对象复制到另外一块上面, 然后再把已使用过的内存空间一次清理掉。 

        如果内存中多数对象都是存活的, 这种算法将会产生大量的内存间复制的开销, 但对于多数对象都是可回收的情况, 算法需要复制的就是占少数的存活对象, 而且每次都是针对整个半区进行内存回收, 分配内存时也就不用考虑有空间碎片的复杂情况, 只要移动堆顶指针, 按顺序分配即可.

 

但是这种算法也有缺点:

  1. 需要提前预留一半的内存区域用来存放存活的对象(经过垃圾收集后还存活的对象),这样导致可用的对象区域减小一半,总体的GC更加频繁了
  2. 如果出现存活对象数量比较多的时候,需要复制较多的对象,成本上升,效率降低
  3. 如果99%的对象都是存活的(老年代),那么老年代是无法使用这种算法的。

注意事项:

        现在的商用Java虚拟机大多都优先采用了这种收集算法去回收新生代, 新生代中的对象有98%熬不过第一轮收集。 因此并不需要按照1∶1的比例来划分新生代的内存空间。Appel式回收的具体做法是把新生代分为一块较大的Eden空间和两块较小的 Survivor空间, 每次分配内存只使用Eden和其中一块Survivor。 发生垃圾搜集时, 将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上, 然后直接清理掉Eden和已用过的那块Survivor空间 HotSpot虚拟机默认 Eden 和 Survivor 的大小比例是8∶1, 也即每次新生代中可用内存空间为整个新生代容量的90%(Eden的80%加上一个Survivor的10%) , 只有一个Survivor空间, 即10%的新生代是会被“浪费”的。

4.标记-整理算法

        标记-复制算法在对象存活率较高时就要进行较多的复制操作, 效率将会降低。 更关键的是, 如果不想浪费50%的空间, 就需要有额外的空间进行分配担保, 以应对被使用的内存中所有对象都100%存活的极端情况, 所以在老年代一般不能直接选用这种算法。

        针对老年代对象的存亡特征, 1974年Edward Lueders提出了另外一种有针对性的“标记-整理”(Mark-Compact) 算法, 其中的标记过程仍然与“标记-清除”算法一样, 但后续步骤不是直接对可回收对象进行清理, 而是让所有存活的对象都向内存空间一端移动, 然后直接清理掉边界以外的内存 。

        标记-清除算法 与 标记-整理算法的本质差异在于前者是一种非移动式的回收算法, 而后者是移动式的。 是否移动回收后的存活对象是一项优缺点并存的风险决策:

 

        是否移动对象都存在弊端, 移动则内存回收时会更复杂, 不移动则内存分配时会更复杂。 从垃圾收集的停顿时间来看, 不移动对象停顿时间会更短, 甚至可以不需要停顿, 但是从整个程序的吞吐量来看, 移动对象会更划算。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM-垃圾收集算法 的相关文章

随机推荐

  • Haproxy负载均衡和动静分离配置

    Haproxy Haproxy安装 yum y install haproxy 配置负载均衡 frontend ds 80 定义前端服务器名为ds 监听地址为所有ip的80端口 default backend webservers 默认请求
  • SSRF(服务端请求伪造)

    SSRF Server side Request Forge 服务端请求伪造 1 概念 它是一种由攻击者构造形成由服务端发起请求的一个安全漏洞 一般情况下 SSRF攻击的目标是从外网无法访问的内部系统 正是因为它是由服务端发起的 所以它能够
  • Linux中的中断机制 2

    Linux中的中断机制 2009 06 11 23 03 44 分类 LINUX Linux中的中断机制 X86里面中断发生时CPU控制单元工作流程 也就是硬件需要做的事情 在CPU执行下一条instruction之前 首先判断有没有发生异
  • unity 2019 点击脚本启动不了VS_Unity-利用免费资源快捷实现第三人称角色控制

    by 临界荷 本例目标 学习使用unity商店免费资源中的模型和代码 轻松快捷实现第三人称视角玩家多种行为的设定 举一反三 可方便灵活地添加到自己的3D模型 绑定了骨骼和动作的人物模型 不支持动物模型 实现步骤 找到并体验资源项目 1 打开
  • Qt常见警告问题:请更新您的工具包(Desktop Qt 5.14.1MSVC2017 64位)或为qmake选择更符合您的目标环境的mkspec

    2021 03 28T17 32 05 Clang Code Model Error The clangbackend executable D Qt Qt5 12 9 Tools QtCreator bin clangbackend ex
  • ORACLE深入 第五章 Locking and Latching

    ORACLE深入 第五章 Locking and Latching Locks 在单用户系统 LOCKS是不需要的 在多用户系统 为了让多用户访问数据 修改数据 修改数据结构 就需要一个机制来保证大家的一致性修改 该用LOCK的时候就用LO
  • Selenium基础知识

    关于selenium你应该知道的 selenium是什么 一个自动化测试的工具 系统测试 测试阶段 单元测试 集成测试 系统测试 验收测试 自动化测试属于 系统测试 自动测试工具 自动化功能测试工具和自动化性能测试 selenium包括什么
  • Salary Changing【Codeforces 1251 D】【二分答案】

    Educational Codeforces Round 75 Rated for Div 2 D 题意 有N名员工和S元钱 然后我们想知道在每一名员工有薪资要求在 li ri 的情况下 我们如何在总共就S元钱的情况下做到员工薪资的中位数最
  • python爬虫 -- 12306登录刷票

    coding utf 8 from splinter browser import Browser from time import sleep import traceback Message phantomjs executable n
  • centos安装rocketmq

    centos安装rocketmq 1 下载rocketmq二进制包 2 解压二进制包 3 修改broker conf 4 修改runbroker sh和runserver sh的JVM参数 5 启动NameServer和Broker 6 安
  • Linux基础知识汇总,收藏

    对于嵌入式而言 大部分人的进阶路线 单片机 gt RTOS gt Linux 下面 针对有单片机 RTOS基础的同学 分享一份入门 Linux 的基础内容 下方超长干货预警 建议先收藏 再观看 Linux 基础 操作系统 操作系统 Oper
  • linux多线程编译

    include
  • 【教程】手把手教你用Clion进行STM32开发【如何优雅の进行嵌入式开发】

    通过Clion进行嵌入式开发 一 工具安装 1 安装Clion 因为众所周知的原因 Clion的安装就不解释了 有需要的同学自行检索 2 安装STM32CubeMX 正常去官网下载最新版的安装就行了 STM32CubeMX STM32Cub
  • LRC算法的Java实现

    项目中要用到 本来想拿来主义 结果没有找到合适的 所有自己写了一个 LRC具体算法如下 1 对需要校验的数据 2n个字符 两两组成一个16进制的数值求和 2 将模值按位取反 3 加1 Java代码实现 输入byte data 返回LRC校验
  • IDEA好用的两款Java代码质量审查插件

    IDEA好用的两款Java代码质量审查插件 两款Java代码质量审查插件 Alibaba代码规约插件 使用方式 SonarLint 使用方式 两款Java代码质量审查插件 Alibaba代码规约插件 SonarLint插件 Alibaba代
  • PCL 间接平差法拟合二维直线

    目录 一 算法原理 二 代码实现 三 结果展示 四 相关链接 一 算法原理 通过传统最小二乘法对点云数据进行二维直线拟合时 可将误差只归因于一个方向上 本文假设误差只存在于 y y y轴方向上 设点云拟合的二维直线方程为 y
  • Java-GUI初步理解

    什么是GUI GUI既图形用户界面 是一种以图形为主体的交互方式 主要包括AWT组件以及Swing组件以及容器 布局和事件相关的类接口 AWT是抽象窗口工具包的简称 其中有像窗口 按钮等组件 而Swing是基于AWT开发的 他的功能更加强大
  • ESP32+idf开发之WIFI通信入门(2)station网络连接

    ESP32 idf开发之WIFI通信入门 2 station网络连接 1 新建工程项目ctrl shift p 选择new project 输入项目名 选择合适项目路径 选择对应的开发板 此处选择自定义 target选择ESP32 moud
  • 数据库管理员DBA

    数据库管理员DBA什么是DBA 数据库管理员 英文是Database Administrator 简称DBA 这个职位对不同的人意味着不同的意义 一个小的软件开发工作室和一个分工高度明细的大公司相比 DBA的职责来得更加宽泛一些 一个公司
  • JVM-垃圾收集算法

    目录 1 分代收集理论 2 标记 清除算法 3 标记 复制算法 4 标记 整理算法 1 分代收集理论 分代思想也很简单 就是根据对象的生命周期将内存划分 然后进行分区管理 当前商业虚拟机的垃圾收集器大多数都遵循了 分代收集 Generati