深入剖析JVM垃圾收集器

news2024/11/15 3:54:54

文章目录

      • 前言
      • 1、新生代垃圾收集器
        • 1.1、Serial
        • 1.2、ParNew
        • 1.3、Parallel Scavenge
      • 2、老年代垃圾收集器
        • 2.1、Serial Old
        • 2.2、Parallel Old
        • 2.3、CMS(Concurrent Mark Sweep)
      • 3、全堆垃圾收集器
        • 3.1、Garbage First(G1)

前言

参考资料:《深入理解Java虚拟机》

垃圾收集器是GC的实践者,目前常用经典的垃圾收集器有7款,如下图所示:
在这里插入图片描述
收集器之间的连线说明可以搭配使用,JDK9标识代表在该版本官方已经不支持配合使用了!

接下来逐一介绍这几款垃圾收集器。

1、新生代垃圾收集器

1.1、Serial

顾名思义,单线程的垃圾收集器;这里的单线程不仅仅说明它只使用一个GC线程进行垃圾收集,更重要的是它进行GC时,其他的工作线程必须暂停,直到GC线程工作结束,这种现象就是大名鼎鼎的STW(Stop The World),这种现象对很多应用来说是不可接受的!

Serial/Serial Old收集器运行示意图:
在这里插入图片描述

1.2、ParNew

ParNew收集器实质是Serial收集器的多线程并行版本

可以认为ParNew除了同时使用多线程进行GC外,其余行为和Serial收集器完全一致(控制参数、STW、回收策略等),ParNew/Serial Old运行示意图如下:
在这里插入图片描述
CMS出现巩固了ParNew的地位,因为新生代只有Serial和ParNew能与CMS配合使用。不过好景不长,更先进的G1全堆垃圾收集器干掉了这对苦命鸳鸯,从JDK9开始,官方希望G1彻底取代这对组合。

ParNew在单核CPU中比Serial效果更差,因为需要频繁的上下文切换;ParNew默认开启的GC线程数与CPU核数相同,可以使用-XX:ParallelGCThreads参数限制GC的线程数。

1.3、Parallel Scavenge

与前两款新生代收集器一样,Parallel Scavenge同样采用标记-复制算法;该收集器还支持多个GC线程并行(看起来和ParNew没啥区别),接下来我们探讨一下它到底有什么特别之处。

该收集器专注于吞吐量吞吐量 = CPU运行用户代码时间 / 运行用户代码时间 + 运行GC时间,高吞吐量可以最高效率利用CPU资源,尽快完成程序运算任务,主要适合在后台运算而不需要太多交互的分析任务。

该收集器通过两个参数精确控制吞吐量

  1. -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间(通过牺牲新生代空间和吞吐量实现)
  2. -XX:GCTimeRatio:直接设置吞吐量大小(默认值99,尽可能保证应用程序执行时间为收集器执行时间的99倍,也就是收集器的时间消耗不超过总运行时间的1%)

相比于ParNew,该收集器最重要的特性自适应调节策略,通过参数-XX:+UseAdaptiveSizePolicy控制,参数激活后,就不需要手动指定新生代、Eden和Survivor区比例、晋升老年代对象大小等细节参数了,JVM会根据当前系统的运行情况收集性能监控信息,动态调整这些参数提供最合适的停顿时间或最大的吞吐量。

2、老年代垃圾收集器

2.1、Serial Old

和Serial基本一致,也是单线程垃圾收集器,只不过Serial使用于新生代,采用复制算法;Serial使用于老年代,采用标记-整理算法,这里就不过多介绍了,运行原理如图:
在这里插入图片描述

2.2、Parallel Old

可以认为它是Parallel Scavenge收集器的老年代版本,这里也不做过多介绍了,大致是一样的,在注重吞吐量或CPU资源稀缺的场合,可以有效考虑使用Parallel Scavenge + Parallel Old组合,运行示意图如下:

在这里插入图片描述

2.3、CMS(Concurrent Mark Sweep)

以获取最短回收停顿时间为目标的收集器。

相比于两外两个收集器,CMS采用的是标记-清除算法,它的运行过程分为四个步骤,其中,初始标记重新标记需要STW:

  1. 初始标记:仅仅标记GC Roots能直接关联到的对象,速度很快
  2. 并发标记:从GC Roots直接关联对象开始,遍历整个对象图的过程,过程耗时较长但不需要停顿用户线程
  3. 重新标记:为了修正并发标记阶段,因用户线程继续运行而导致标记产生变动那部分对象的标记记录,停顿时间大于初始标记,小于并发标记
  4. 并发清除:清除标记阶段判断的已经死亡对象,该阶段可以与用户线程同时并行

在这里插入图片描述

CMS有三个明显的缺点:

  1. CMS对CPU资源十分敏感
    虽然CMS不会造成用户线程停顿,但是会因为占用了一部分线程而导致应用程序变慢,降低总吞吐量
  2. CMS无法处理浮动垃圾
    有可能出现Con-current Mode Failure失败进而导致另一次STW的Full GC产生。在CMS并发标记和并发清理阶段,用户线程还是在运行,自然就会有新的垃圾对象产生,这部分对象还是在标记过程结束后产生的,CMS无法在本次GC过程中处理掉它们,只能等到下一次清除;所以CMS不能像其他收集器那样等到老年代几乎填满在收集,必须预留一部分空间以供并发收集时程序运作使用。可以通过参数-XX:CMSInitiatingOccu-pancyFraction控制CMS触发百分比,设置太高容易造成大量的并发失败产生,设置太低会导致频繁进行GC
  3. CMS采用标记-清除算法,所以会有内存碎片问题

3、全堆垃圾收集器

3.1、Garbage First(G1)

G1开创了面向局部收集设计思路和基于Region的内存布局形式。

G1把连续的堆内存划分为多个大小相等的独立区域(Region),每个Region都可以根据需要扮演成Eden、Survivor、老年代空间,针对不同角色的Region采用不同的策略去处理,获取很好的收集结果。

Region中有一类特殊的Humongous区域,专门用于存储大对象。
G1认为只要大小超过一个Region一半的对象皆为大对象(Region大小可以通过参数-XX:G1HeapRegionSize设定,范围为1~32MB)。对于超过了整个Region容量的超级大对象会被存放在N个连续的Humongous Region中,G1将其看作老年代的一部分。

G1每次GC的内存空间都是Region大小的整数倍,它会跟踪每个Region垃圾价值大小,价值即回收所获得的空间大小以及回收所需的时间经验值,然后在后台维护一个优先级列表,优先回收收益最大的那些Region。

在这里插入图片描述

G1收集器的运作过程大致可划分为以下四个步骤:

  1. 初始标记:仅仅标记GC Roots直接关联的对象,并且修改TAMS指针,让下个阶段用户线程并发运行时正确地在可用的Region中分配新对象,耗时很短。
  2. 并发标记:从GC Root开始对堆中对象进行可达性分析,找到要回收的对象,可与用户线程并发执行,耗时较长。
  3. 最终标记:用户线程短暂暂停,用于处理并发阶段结束后遗留下来的最后那少量的SATB记录。
  4. 筛选回收:对各个Region根据回收价值和成本进行排序,根据用户期望停顿时间制定回收计划,自由选择任意多个Region作为回收集,然后把决定回收的部分Region存活对象复制到空的Region中,再清理掉整个旧Region全部空间。这里涉及对象的移动必须是暂停用户线程,多条GC线程并行完成。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ConfigurationProperties将配置绑定到bean的过程分析

概述 ConfigurationProperties是一个大家常用的注解。有一些系统配置,经常放在yml中,然后通过spring注入到bean中。 一般这些配置都是通过在spring生命周期的某一个环节,将属性注入进去的。 ConfigurationProperties就是利用了org.springf…

AC500 基于 Profinet 通讯连接变频器

硬件连接 使用 PM583-ETH 作为 Profinet 通讯的主站,ACS800 变频器 RETA-02 作为 Profinet 通讯的从站 2 ABB 变频器设置 以安装有 RETA-02 总线适配器的 ACS800 变频器为例,参照下表进行参数设定。详 细内容请参考变频器手册和 RETA-02 用户手册。表中…

Python 超强命令行解析工具 argparse !

在工作中,我们经常需要从命令行当中解析出指定的参数,而 Python 也提供了相应的标准库来做这件事情,比如 sys, optparse, getopt, argparse。这里面功能最强大的莫过于 argparse,下面就来看看它用法。import argparse# 使用 argpa…

计算机视觉OpenCv学习系列:第七部分、图像操作-3

第七部分、图像操作-3第一节、图像统计信息1.像素值统计2.函数支持说明3.代码练习与测试第二节、图像直方图1.图像直方图定义2.直方图函数3.代码练习与测试第三节、图像直方图均衡化1.直方图均衡化2.直方图均衡化函数3.代码练习与测试学习参考第一节、图像统计信息 1.像素值统…

零基础学JavaWeb开发(二十一)之 spring框架(4)

3、AOP详解 3.1、Aop常用术语 1.连接点(Join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。类中的哪些方法可以被增强,这些…

详解动态规划01背包问题--JavaScript实现

对其他动态规划问题感兴趣的,也可以查看详解动态规划最少硬币找零问题--JavaScript实现详解动态规划最长公共子序列--JavaScript实现一开始在接触动态规划的时候,可能会云里雾里,似乎能理解思路,但是又无法准确地表述或者把代码写…

车辆占用应急车道识别抓拍系统 opencv

车辆占用应急车道识别抓拍系统通过opencvpython人工智能识别技术,对高速公路应急车道进行不间断实时监测,当监测到应急车道上有车辆违规占用时,立即告警提醒后台人员及时处理避。OpenCV的全称是Open Source Computer Vision Library&#xff…

【18】C语言 | 数组详解

目录 1、数组的格式 2、下列有什么区别 3、维数组的使用 4、*p 和 int* p arr 的含义 5、二维数组:打印一个二维数组 6、二维数组在数组中的存储 7、数组作为函数参数 8、数组名是数组首元素的地址 1、数组的格式 数组是一组相同类型元素的集合。 数组的创…

20230123英语学习

Interesting Studies to Spark Your Interest in the Research Field 科研也可以很有趣!盘点那些好玩的研究 When it comes to picking studies worth reading, what scientists deem an interesting science article might be perceived differently by a person…

【Datewhale一起吃瓜 Task2】啃瓜第三章

文章目录线性模型关键:找到合适的w和b如何找到合适的 w和b?偏导为什么可以?推广线性模型 任务:找出一条线能够对数据进行划分或预测趋势 关键:找到合适的w和b 更适合于连续性的数值,如果数据是离散的如色…

AcWing 1020. 潜水员(二维费用背包)

一、问题 二、思路 这道题其实很容易看出是一个二维费用背包的变形,如果我们将氧气看作体积,将氮气看作价值的话,这道题就变成了从iii个物品里面选,体积至少为mmm,价值至少为nnn的条件下,所携带的物品的最…

Maplab:一个用于视觉惯性建图和定位研究的开源框架

摘要 鲁棒且精确的视觉惯性估计是当今机器人领域的重要挑战。能够用先验地图(prior map)进行定位(localize)并获得准确且无漂移的姿态估计,可以推动该系统的适应性。然而,目前大多数可用的解决方案都集中在单次使用,缺乏定位能力或端到端流水…

Java基本类型和包装类什么情况下判断相等(“==“或“equals“)?

[1] 先讨论一个面试题 int a 1; Integer b 1; Integer c new Integer(1); Integer d Integer.valueOf(1); int e d; int f d.intValue();请问以下式子的值?为什么? a b // true a c // true b c // false[2] ""与"equals"…

C++设计新思维(泛型编程与设计模式之应用)之常整数映射为类别(2.4)

技术 模板偏特化,模板全特化 应用 1、有必要根据一个编译期常数调用一个或数个不同的函数 2、有必要在编译器实施"分派"(dispatch) 例子 如果打算在执行期进行分派(dispatch),可使用if-else或switch语句。大部分时候其执行期成本都微不足…

windows权限维持方法详解

权限维持在获取服务器权限后,为了防止服务器管理员发现和修补漏洞而导致对服务器权限的丢失,测试人员往往需要采取一些手段来实现对目标服务器的持久化访问。权限持久化(权限维持)技术就是包括任何可以被测试人员用来在系统重启、…

Allegro如何通过飞线判断同一个网络连接位是否在同一直线操作指导

Allegro如何通过飞线判断同一个网络连接位是否在同一直线操作指导 Allegro可以通过飞线判断同一个网络的连接位是否在同一条直线上,如下图 当飞线是类似三角形的时候,可以判定两个连接点位是在同一条直线上 具体设置操作如下 选择Setup选择Design Parameter

React源码之render过程中发生了什么?

理解JSX 对于我们直接书写jsx语法&#xff0c;我们的浏览器是不理解我们这种语法的&#xff0c;所以需要babel来去转义&#xff0c;那么可以通过plugin-transform-react-jsx来转译jsx语法&#xff0c;使得浏览器可以识别我们的Jsx语法&#xff0c;例如&#xff1a; <div&g…

关于xshell简答使用

xshell是一个远程工具下载 官网地址&#xff1a;https://www.xshell.com/zh/xshell/直接下载即可~选择免费的授权页面 下载 不然要收费 也不要用盗版。运行后的xshell界面我们要建立服务器的连接点击加号 新建连接 即可 输入连接地址后 要输入 账号 和 秘密 OK 好了 可以使用了…

【Linux】Linux编译器gcc、g++

文章目录&#x1f3aa; Linux编译器gcc、g&#x1f680;1. 程序的编译⭐1.1 预处理⭐1.2 编译⭐1.3 汇编⭐1.4 链接⭐1.5 gcc/g常用指令&#x1f680;2. 函数库⭐2.1 静态库⭐2.2 动态库⭐2.3 动静态库对比&#x1f3aa; Linux编译器gcc、g 我们这以gcc为例&#xff0c;g编译器…

【学习笔记之数据结构】树的认识

树的概念&#xff1a; 树是一种非线性的数据结构&#xff0c;它由n&#xff08;n可以为0&#xff09;个有限的节点组成一个具有层次关系的结合。之所以把它称之为树是因为它的逻辑结构形似一个倒着的树。它的根在上面&#xff0c;叶子在下面。   有一个特殊的节点&#xff0c…