G1收集器特质以及分代理论

2023-10-27

特征

被视为JDK1.7以上版本Java虚拟机的一个重要进化特征。它具备以下特点:

  • 并行与并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程来执行GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。
  • 分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。
  • 空间整合:与CMS的“标记–清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
  • 可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1 和 CMS 共同的关注点,但G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段(通过参数"-XX:MaxGCPauseMillis"指定)内完成垃圾收集。

毫无疑问, 可以由用户指定期望的停顿时间是G1收集器很强大的一个功能, 设置不同的期望停顿时间, 可使得G1在不同应用场景中取得关注吞吐量和关注延迟之间的最佳平衡。 不过, 这里设置的“期望值”必须是符合实际的, 不能异想天开, 毕竟G1是要冻结用户线程来复制对象的, 这个停顿时间再怎么低也得有个限度。 它默认的停顿目标为两百毫秒, 一般来说, 回收阶段占到几十到一百甚至接近两百毫秒都很正常,

 但如果我们把停顿时间调得非常低, 譬如设置为二十毫秒, 很可能出现的结果就是由于停顿目标时间太短, 导致每次选出来的回收集只占堆内存很小的一部分, 收集器收集的速度逐渐跟不上分配器分配的速度, 导致垃圾慢慢堆积。 很可能一开始收集器还能从空闲的堆内存中获得一些喘息的时间, 但应用运行时间一长就不行了, 最终占满堆引发Full GC反而降低性能, 所以通常把期望停顿时间设置为一两百毫秒或者两三百毫秒会是比较合理的

G1垃圾收集分类

YoungGC
        YoungGC并不是说现有的Eden区放满了就会马上触发,G1会计算下现在Eden区回收大概要多久时间,如果回收时间远远小于参数 -XX:MaxGCPauseMills 设定的值,那么增加年轻代的region,继续给新对象存放,不会马上做Young GC,直到下一次Eden区放满,G1计算回收时间接近参数 -XX:MaxGCPauseMills 设定的值,那么就会触发Young GC
MixedGC
        不是FullGC,老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发,回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区正常情况G1的垃圾收集是先做MixedGC,主要使用复制算法,需要把各个region中存活的对象拷贝到别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC
Full GC
        停止系统程序,然后采用单线程进行标记、清理和压缩整理,好空闲出来一批Region来供下一次MixedGC使用,这个过程是非常耗时的。(Shenandoah优化成多线程收集了)

G1垃圾收集器优化建议

假设参数 -XX:MaxGCPauseMills 设置的值很大,导致系统运行很久,年轻代可能都占用了堆内存的60%了,此时才触发年轻代gc。
那么存活下来的对象可能就会很多,此时就会导致Survivor区域放不下那么多的对象,就会进入老年代中。
或者是你年轻代gc过后,存活下来的对象过多,导致进入Survivor区域后触发了动态年龄判定规则,达到了Survivor区域的50%,也会快速导致一些对象进入老年代中。
所以这里核心还是在于调节 -XX:MaxGCPauseMills 这个参数的值,在保证他的年轻代gc别太频繁的同时,还得考虑每次gc过后的存活对象有多少,避免存活对象太多快速进入老年代,频繁触发mixed gc.

什么场景适合使用G1

  1. 50%以上的堆被存活对象占用
  2. 对象分配和晋升的速度变化非常大
  3. 垃圾回收时间特别长,超过1秒
  4. 8GB以上的堆内存(建议值)
  5. 停顿时间是500ms以内

并行于并发

  1. 并行性:G1在回收期间,可以有多个GC线程,有效利用多核计算能力,此时用户线程STW。
  2. 并发性:G1有和应用线程交替执行的能力,部分工作可以和应用程序同时进行。一般来说不会发生在回收过程中完全阻塞应用线程。

分代收集

  1. 从分代上看,G1依然属于分代型垃圾回收器,它会区分年轻代和老年代,年轻代依然有Eden区和Survivor区。但从堆的结构上看,它不要求整个Eden区、年轻代或者老年代都是连续的,也不再坚持固定大小和固定数量。
  2. 将堆空间分为若千个区域(Region) , 这些区域中包含了逻辑上的年轻代和老年代。
  3. 和之前的各类回收器不同,它同时兼顾年轻代和老年代。对比其他回收器,或者工作在年轻代,或者工作在老年代。

空间整合

  1. CMS:CMS:“标记- 清除”算法、内存碎片、若干次GC后进行一次碎片整理
  2. G1将内存划分为一个个的region.内存的回收是以region作为基本单位的 Region之间是复制算法,但整体上实际可看作是标记-整理算法,两种算法都可以避免内存碎片。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。尤其是当Java堆非常大的时候,G1的优势更加明显。

可预测停顿

这是G1相对于CMS的另一大优势,G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在-一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N亳秒。

  1. 由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收的范围,因此对于全局停顿情况的发生也能得到较好的控制。
  2. G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大Region.保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。

缺点

  1. 相较于CMS,G1还不具备全方位、压倒性优势。比如在用户程序运行过程中,G1无论是为了垃圾收集产生的内存占用(Footprint) 还是程序运行时的额外执行负载(Overload) 都要比CMS要高。
  2. 从经验上来说,在小内存应用上CMS的表现大概率会优于G1,而G1在大内存应用上则发挥其优势。平衡点在6-8GB之间

每秒几十万并发的系统如何优化JVM

        Kafka类似的支撑高并发消息系统大家肯定不陌生,对于kafka来说,每秒处理几万甚至几十万消息时很正常的,一般来说部署kafka需要用大内存机器(比如64G),也就是说可以给年轻代分配个三四十G的内存用来支撑高并发处理,这里就涉及到一个问题了,我们以前常说的对于eden区的young gc是很快的,这种情况下它的执行还会很快吗?很显然,不可能,因为内存太大,处理还是要花不少时间的,假设三四十G内存回收可能最快也要几秒钟,按kafka这个并发量放满三四十G的eden区可能也就一两分钟吧,那么意味着整个系统每运行一两分钟就会因为young gc卡顿几秒钟没法处理新消息,显然是不行的。那么对于这种情况如何优化了,我们可以使用G1收集器,设置 -XX:MaxGCPauseMills 为50ms,假设50ms能够回收三到四个G内存,然后50ms的卡顿其实完全能够接受,用户几乎无感知,那么整个系统就可以在卡顿几乎无感知的情况下一边处理业务一边收集垃圾。G1天生就适合这种大内存机器的JVM运行,可以比较完美的解决大内存垃圾回收时间过长的问题。

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

G1收集器特质以及分代理论 的相关文章

  • Java 接口合成方法生成,同时缩小返回类型

    我有 2 个接口和 2 个返回类型 interface interfaceA Publisher
  • JVM 是否会内联对象的实例变量和方法?

    假设我有一个非常紧密的内部循环 每次迭代都会访问和改变一个簿记对象 该对象存储有关算法的一些简单数据 并具有用于操作它的简单逻辑 簿记对象是私有的和最终的 并且它的所有方法都是私有的 最终的和 inline 下面是一个示例 Scala 语法
  • 在 HP Load Runner 的 VuGen 中加载 javai.dll 时出现错误

    当我尝试在 HP load runner 的 VuGen 中编译一个简单的脚本时 无法启动 JVM 并出现以下错误 Java VM Internal Error Getting Error Loading javai dll 我在用着 HP
  • 在正在运行的 JVM 中查找正在运行的实例

    我想知道是否可以获取给定类的正在运行的实例的句柄 触发此问题的特定问题是应用程序由于存在大量正在运行的线程而无法正常退出 是的 我知道您可以对 thead 进行守护进程 然后它们就不会阻止应用程序退出 但这确实让我想知道这是否可能 我能做的
  • JVM内存段分配

    好吧 我有一个关于 JVM 内存段的问题 我知道每个 JVM 都会选择稍微不同地实现这一点 但这是一个总体概念 在所有 JVM 中应该保持相同 一个在运行时不使用虚拟机执行的标准C C 程序在运行时有四个内存段 代码 堆栈 堆 数据 所有这
  • Java 语言中不可用的字节码功能

    当前 Java 6 是否有一些事情可以在 Java 字节码中完成而在 Java 语言中无法完成 我知道两者都是图灵完备的 所以将 可以做 理解为 可以做得更快 更好 或者只是以不同的方式 我正在考虑额外的字节码 例如invokedynami
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • 如果使用的 JVM 是 x86 或 x64,则以不同的方式解决 Maven 依赖关系?

    我设置了一个 Maven 存储库来托管一些 dll 但我需要我的 Maven 项目根据使用的 JVM 是 x86 还是 x64 下载不同的 dll 例如 在运行 x86 版本 JVM 的计算机上 我需要从存储库下载 ABC dll 作为依赖
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • Java中的整数缓存[重复]

    这个问题在这里已经有答案了 可能的重复 奇怪的Java拳击 https stackoverflow com questions 3130311 weird java boxing 最近我看到一个演示 其中有以下 Java 代码示例 Inte
  • ASM之前看一下maxStack指令吗?

    我正在尝试使用 ASM 库将字节代码转换为不同的格式 这可以使用 MethodVisitor 来完成 就像这个简单的测试代码一样 return new MethodVisitor ASM7 Override public void visi
  • 使用 Coldfusion 11 的 CFdirectory,文件名中存在非 ASCII 字符问题

    我有一个类似的问题 ColdFusion CFDirectory 和法语 https stackoverflow com questions 1715632 coldfusion cfdirectory and the french从而没有
  • 是否可以强制 JVM 在堆中而不是堆中创建对象?

    我读过一些文章 有时JVM会识别一些对象并尝试在堆栈中而不是堆中创建它 因为堆栈上的内存分配比堆中的内存分配便宜 堆栈上的释放是免费的 并且堆栈由以下方式有效管理 运行时 那么 堆栈中的对象分配是如何工作的 有什么方法可以强制 JVM 执行
  • Java:VM 如何在 32 位处理器上处理 64 位“long”

    JVM 如何在 32 位处理器上处理 64 位的原始 long 在多核 32 位机器上可以并行利用多个核心吗 64 位操作在 32 位机器上慢了多少 它可能使用多个核心来运行不同的线程 但不会并行使用它们进行 64 位计算 64 位长基本上
  • Java 加载类时如何管理内存?

    想象一下 我有一个包含 10 个方法的类 我需要从该类中实例化 10 个对象 问题是 JVM 会在对象创建时为 10 个实例分配 10 个不同的内存空间 我的意思是在我调用构造函数时 即 new MyClass 吗 或者它会在内存中加载一次
  • 使用同一类的不同版本进行类加载:java.lang.LinkageError:尝试重复名称的类定义

    我有一个工作代码 可以动态加载具有不同类名的不同类实现 类文件被加载到内存数据库 Apache 德比数据库 类加载器检索 class文件来自BLOB列 我想做的是插入 class文件为带有版本列的二进制 BLOB 和IS ENABLED标志
  • 有没有一种独立的JAVA可以在PC上运行而无需任何操作系统

    据我所知 java 程序可以在任何操作系统上运行 任何类型的机器都有 JVM 我需要一个在我的 PC 上独立运行的 JVM 而不是在我的操作系统 Windows 或任何其他操作系统 上运行 我的意思是 JVM 的作用类似于启动 而不是操作系
  • 从 Java 内部限制 CPU

    我在这个 和其他 论坛中看到了许多具有相同标题的问题 但似乎没有一个问题能完全解决我的问题 就是这个 我有一个 JVM 它占用了托管它的机器上的所有 CPU 我想限制它 但是我不能依赖任何限制工具 技术external到 Java 因为我无
  • 附加到已经运行的 JVM

    有没有办法附加到已经运行的 JVM 例如 在 JNI 中您可以使用JNI CreateJavaVM创建一个虚拟机并运行一个 jar 并检查它的所有类 但是 如果 jar 已经在运行 我找不到附加到其 JVM 并与其类通信或获取其的方法env
  • 这些用简单的java代码创建的JVM守护线程是什么?

    我有一个非常简单的java应用程序 它只是创建一个对象 调用它的一个函数 所有这些都在一个无限循环中 public class h public static void main String args while true B b new

随机推荐

  • 软件项目管理 3.5.敏捷生存期模型

    前言 大家好 这节我们学习敏捷模型 前面介绍的几种生存期模型在实际应用过程中遇到的一些挑战 有时不能很好地适应需求的快速变化 为此软件界比较流行敏捷生命期模型 一 敏捷模型 敏捷宣言 价值观 原则 和通用实践之间的关系 敏捷模型符合敏捷宣言
  • CNN的重点整理

    1 常用的非线性激活函数 sigmoid tanh relu等等 前两者sigmoid tanh比较常见于全链接层 后者relu常见于卷积层 这里先简要介绍下最基础的sigmoid函数 btw 在本博客中SVM那篇文章开头有提过 sigmo
  • 染色——差分数组板子题

    问题描述 有编号为0到M 的 M 1 个格子 现在有N个操作 x y 表示将从x 到 y的格子染色 问一共有多少个格子被染色 输入 第一行两个整数 分别表示N和M 接下来有N行 每行两个整数 分别表示x和y 输出 输出一个整数 表示有多少个
  • [YOLO专题-12]:YOLO V5 - ultralytics支持的5种不同规模的模型类型比较

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122294915 目录 1 概述 2
  • VR引擎哪家强?主流VR开发引擎大起底

    转载自 http www hiavr com news tech 22826 html ref myread 在VR浪潮面前 Unreal Unity CryENGINE各大游戏引擎纷纷跟进 都决心抓住这个绝无仅有的机会 一举奠定自己的江湖
  • AutoML-A survey of the state-of-the art翻译+总结

    AutoML A Survey of the State of the Art Abstract 深度学习 DL 技术已经渗透到我们生活的各个方面 给我们带来了极大的方便 然而 为特定任务构建高质量的DL系统高度依赖于人类的专业知识 这阻碍
  • Docker 镜像基本命令操作

    目录标题 Docker 镜像基本命令操作 一 Docker 安装 二 镜像操作 Docker 镜像基本命令操作 一 Docker 安装 Docker要求运行在Centos 7上 要求系统为64位 系统内核版本3 10以上 1 uname a
  • 鸿蒙os更新名单,鸿蒙系统首批升级名单 华为鸿蒙系统升级机型名单时间表

    2021年6月2日 在这天华为公布了一直津津乐道的鸿蒙系统 并且推出了HarmonyOS2百机升级计划 一共是分为四个阶段来进行升级 很多朋友还不清楚升级的机型名单和时间都是多少 下面就来为大家分享一下 第一批升级名单 6月2日就可以升级
  • 单电源运放滤波器设计

    在很多情况中 为了阻挡由于虚地引起的直流电平 在 运放的输入端串入了电容 这个电容实际上是一个高通滤波器 在某种意义上说 像这样的单电源运放电 路都有这样的电容 设计者必须确定这个电容的容量必须要比电路中的其他电容器的容量大 100倍以上
  • 模拟开关选型、多路复用器选型

    只列举常用的 芯片均出自TI ADI SGM Nexperia等 国产只考虑CH 泌恒 个人整理 tb均能买到 如有纰漏欢迎纠错
  • 残差网络、Dropout正则化、Batch Normalization浅了解

    残差网络 为什么需要残差网络 残差网络的目的是为了解决深度神经网络在训练过程中遇到的退化问题 即随着网络层数的增加 训练集的误差反而增大 而不是过拟合 残差网络的优点有以下几点 残差网络可以有效地缓解梯度消失或爆炸的问题 因为跳跃连接可以提
  • Python中如何将浮点型数据转换成整型

    在 Python 中 可以使用内置函数 int 将浮点型数据转换为整型 例如 a 3 14 b int a print b 输出结果为 3 注意 转换为整型时 会将浮点数四舍五入到最接近的整数
  • Android 创建淡入淡出动画的详解

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 介绍 淡入淡出动画 也称为 叠化 逐渐淡出一个 View 或 ViewGroup 同时淡入另一个 此动画适用于您希望在应用中切换内容或视
  • 华为机考 创建二叉树 javascript

    请按下列描达构建一颗二叉树 并返回该树的根节点 1 先创建值为 1的根结点 根节点在第0层 2 然后根据operations依次添加节点 operations i height index 表示对第 height 层的第index 个节点n
  • 适合小白入门Spark的全面教程

    问题导读1 spark有哪些使用场景 2 spark有包含哪些组件 3 spark在哪些厂商已经应用 4 spark如何实现地震检测 Apache Spark是一个用于实时处理的开源集群计算框架 它是Apache软件基金会中最成功的项目 S
  • python学习3. 无重复字符的最长子串(滑动窗口)

    makcooo 2019 04 19 15 47 32 271 收藏 分类专栏 python 版权 给定一个字符串 请你找出其中不含有重复字符的 最长子串 的长度 示例 1 输入 abcabcbb 输出 3 解释 因为无重复字符的最长子串是
  • impala对元数据的界面更新操作

    执行 impala shell 即能进入界面操作sql 如果在hive更新了数据之后 而在impala中却无法看到更新后的数据的话 意味着impala里元数据信息还没有刷新 此时在impala操作界面里 执行 invalidate meta
  • 随机数生成方法及其应用

    目录 一 前言 二 伪随机数发生器介绍 三 均匀随机数发生器 四 任意概率分布的随机数发生器 五 产生特定要求的随机数 六 参考资料 一 前言 最近公司的一个项目 需要对一个功能模块进行性能验证 具体什么模块就不说了 验证过程中需要生成大量
  • 2022 年 5 个新 sudo 功能

    导读 最近的 sudo 版本增加了新的功能 使你能够观察和控制以前隐藏的问题 当你想授予你的一些用户管理权限 同时控制和检查他们在你的系统上做什么时 你会使用 sudo 然而 即使是 sudo 也有相当多不可控的地方 想想给予 shell
  • G1收集器特质以及分代理论

    特征 被视为JDK1 7以上版本Java虚拟机的一个重要进化特征 它具备以下特点 并行与并发 G1能充分利用CPU 多核环境下的硬件优势 使用多个CPU CPU或者CPU核心 来缩短Stop The World停顿时间 部分其他收集器原本需