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-垃圾收集算法 的相关文章

  • 如何获取枚举的子集

    大多数情况下 包含所有元素的枚举显示在用户界面的下拉列表中 我们只需要在用户界面中显示 5 个字段中的 2 个 通过某种方式利用可用于枚举的相同函数来获取此数据的更简单方法是什么 enum Color RED GREEN BLACK BLU
  • 哪个类调用了我的静态方法?

    假设我有一个带有静态方法的 Java 类 如下所示 class A static void foo Which class invoked me 进一步假设 A 类有任意数量的子类 class B extends A class C ext
  • 在 MongoDB Java 驱动程序中如何使用 $filter

    我有一个适用于 MQL 的查询 我需要将其翻译成Java MQL 中的查询如下所示 db
  • 从 Bitmap 类创建 .bmp 图像文件

    我创建了一个使用套接字的应用程序 客户端在其中接收图像并将图像数据存储在 Bitmap 类中 谁能告诉我如何创建一个名为我的图像 png or 我的图像 bmp来自此 Bitmap 对象 String base64Code dataInpu
  • 隐藏类的 System.out.print 调用

    我正在使用 java 库 jar 文件 该文件的作者放入了一堆System out print and System out printlns 有没有办法隐藏特定对象的这些消息 编辑 看起来jar文件似乎正在创建一堆线程 并且每个线程都有它
  • DateTimeFormatter.parseLocalDate 抛出 UnsupportedOperationException

    该API用于解析本地日期 http joda time sourceforge net apidocs org joda time format DateTimeFormatter html parseLocalDate 28java la
  • 我需要显式关闭连接吗?

    我持有一个实例MongoClient and DB在我的应用程序中 每次我想执行某些操作时 我都会调用getCollection 我想知道是否需要显式关闭连接 就像connection close 在 JDBC 中 强调一下 我只有一个Mo
  • Spring 术语中命令、表单、业务和实体对象之间的区别?

    我试图理解这些对象在松散耦合系统方面的差异 业务对象与实体对象相同吗 我可以使用 MVC 中的业务或实体对象作为我的命令对象吗 命令对象与表单对象相同吗 只是寻找 Spring 术语和用法中对象类型的说明 我在 stackoverflow
  • Java中无参数的for循环

    我在看别人的代码 发现了这段代码 for 我不是 Java 专家 这行代码在做什么 起初 我认为这会创建一个无限循环 但在该程序员使用的同一个类中 while true 其中 如果我错了 请纠正我 是一个无限循环 这两个相同吗 为什么有人会
  • 使用 Java 通过 HTTP 下载未知长度的文件

    我想用java下载一个HTTP查询 但是我下载的文件在下载时有一个未确定的长度 我认为这将是相当标准的 所以我搜索并找到了它的代码片段 http snipplr com view 33805 http snipplr com view 33
  • 多对多不检索映射数据

    Spring boot 2 5 6 我无法安装版本 概要文件 java Getter Setter NoArgsConstructor AllArgsConstructor EqualsAndHashCode FieldDefaults l
  • 我可以关闭并重新打开套接字吗?

    我学习了一个使用套接字的例子 在此示例中 客户端向服务器发送请求以打开套接字 然后服务器 侦听特定端口 打开套接字 一切都很好 套接字从双方 客户端和服务器 打开 但我仍然不清楚这个东西有多灵活 例如 客户端是否可以关闭一个打开的 从两端
  • Storm Spout 未收到 Ack

    我已经开始使用storm 所以我使用创建简单的拓扑本教程 https github com nathanmarz storm wiki Tutorial 当我运行我的拓扑时LocalCluster一切看起来都很好 我的问题是我没有得到元组的
  • 将变量从 jenkins 传递到 testng.xml

    我想根据从詹金斯传递的变量运行测试用例 例如 选择您要运行的测试用例 测试用例一 测试用例二 在 pom xml maven 中
  • Apache Kafka 是否提供异步订阅回调 API?

    我的项目正在将 Apache Kafka 视为老化的基于 JMS 的消息传递方法的潜在替代品 为了让这个过渡尽可能的顺利 如果替代的排队系统 Kafka 有一个异步订阅机制那就更理想了 类似于我们当前项目使用的JMS机制MessageLis
  • Microsoft JDBC 中的 JTDS 属性相当于什么?

    我正在将 JTDS 连接更改为 Microsoft JDBC 并且我看到存在于http jtds sourceforge net faq html http jtds sourceforge net faq htmlMicrosoft JD
  • 如何修改生成的SOAP请求?

    我正处于创建输出拦截器并从 SOAP 消息中获取 OuputStream 的阶段 但是 如何在将 SOAP 信封发送到端点之前对其进行修改呢 我想删除一些 xml 元素 一种方法是获取文档并通过 XSLT 转换运行它 您可以通过调用来获取拦
  • 如何使用 Nimbus LookAndFeel 更改 JToolTip 的背景颜色?

    在使用 Nimbus LookAndFeel 的基于 Swing 的 Java 应用程序中 我尝试设置工具提示的背景颜色 因此 我创建了 JToolTip 的子类 并通过重写 createToolTip 在我的组件中使用它 到目前为止一切正
  • JSP 和 scriptlet

    我知道现在使用 scriptlet 被认为是禁忌 没关系 我会同意Top Star的话 因为我目前只是Java新手 到目前为止我听到的是 它是为了让设计师的生活更轻松 但我想知道 这是否与JSP页面的性能有关 另一方面 如果只是为了 让设计
  • 升级到 Tomcat 8 时出现 ClassNotFoundException

    我最近将 NetBeans IDE 从 v7 3 升级到 v8 突然我的应用程序在连接到数据库时在服务器启动时抛出异常 这两个版本的 IDE 之间的唯一区别是后者使用 Tomcat 8 异常日志 javax naming NamingExc

随机推荐

  • 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