JVM -- 垃圾回收器7种(四)

news/2024/5/5 19:17:50/文章来源:https://blog.csdn.net/MinggeQingchun/article/details/127093159

阅读前可参考

https://blog.csdn.net/MinggeQingchun/article/details/126947384

https://blog.csdn.net/MinggeQingchun/article/details/127066302

https://blog.csdn.net/MinggeQingchun/article/details/127089533

JVM官方调优指南

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/

一、评估GC的性能指标

1、吞吐量(throughput)

吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值

即吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)

运行用户代码的时间占总时间的比例 (总运行时间::程序运行时间+内存回收时间)

垃圾收集开销:吞吐量的补数,垃圾收集器所用时间与总时间的比例

高吞吐量的情况下,应用程序能容忍较高的暂停时间,因此高吞吐量的应用程序由更长的时间基准,快速响应是不必考虑的

2、暂停时间(响应时间优先)

暂停时间是指一个时间段内应用程序线程暂停,让GC线程执行的状态

执行垃圾收集时,程序的工作线程被暂停的时间

收集频率:相对于应用程序的执行,收集操作发生的频率

3、内存占用:Java堆区所占的内存大小

快速:一个对象从诞生到被回收所经历的时间

这三者共同构成一个"不可能三角",三者总体的表现随着技术的进步越来越好,一款优秀的收集器通常最多同时满足其中两项

现在标准:在最大吞吐量优先的情况下,降低暂停时间吞吐量(throughput)

二、垃圾回收器分类

1、按线程数分

可分为串行垃圾回收器和并行垃圾回收器

2、按工作模式分

可分为并发式垃圾回收器和独占式垃圾回收器

3、按碎片处理方式分

可分为压缩式垃圾回收器和非压缩式垃圾回收器

4、按工作的内存空间分

可分为年起代垃圾收集器和老年代垃圾收集器

三、 七种经典垃圾回收器

JVM的垃圾回收器大体上的分类主要包括四种:串行、并行、并发(CMS)和G1

串行垃圾回收器(Serial):它为单线程环境设计并且只使用一个线程进行垃圾回收,会暂停所有的用户线程。所以不适合服务器环境

并行垃圾回收器(Parallel):多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景

并发垃圾回收器(CMS):用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程。互联网公司多用它,适用于对响应时间有要求的场景

G1垃圾回收器:G1垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收

---------------------------------------------------------------------------------------------------------------------------------

新生代回收器:Serial、ParNew、Parallel Scavenge

老年代回收器:CMS、Serial Old、Parallel Old

全堆:G1

新生代和老年代区域的回收器之间可以搭配使用

(一)新生代回收器:Serial、ParNew、Parallel Scavenge

1、Serial 垃圾回收器

Serial收集器是最基本的、发展历史最悠久的收集器。俗称为:串行回收器,采用复制算法进行垃圾回收

特点

串行回收器是指使用单线程进行垃圾回收的回收器。每次回收时,串行回收器只有一个工作线程。

对于并行能力较弱的单CPU计算机来说,串行回收器的专注性和独占性往往有更好的性能表现。

它存在Stop The World问题,即垃圾回收时,要停止程序的运行。

使用-XX:+UseSerialGC参数可以设置新生代使用这个串行回收器

2、ParNew 垃圾回收器

ParNew其实就是Serial的多线程版本,除了使用多线程之外,其余参数和Serial一模一样。俗称:并行垃圾回收器,采用复制算法进行垃圾回收

特点

ParNew默认开启的线程数与CPU数量相同,在CPU核数很多的机器上,可以通过参数-XX:ParallelGCThreads来设置线程数

它是目前新生代首选的垃圾回收器,因为除了ParNew之外,它是唯一一个能与老年代CMS配合工作的。

它同样存在Stop The World问题

使用-XX:+UseParNewGC参数可以设置新生代使用这个并行回收器

3、ParallelGC 回收器

ParallelGC使用复制算法回收垃圾,也是多线程的

特点

ParallelGC是非常关注系统的吞吐量,吞吐量=代码运行时间/(代码运行时间+垃圾收集时间)

-XX:MaxGCPauseMillis:设置最大垃圾收集停顿时间,可用把虚拟机在GC停顿的时间控制在MaxGCPauseMillis范围内,如果希望减少GC停顿时间可以将MaxGCPauseMillis设置的很小,但是会导致GC频繁,从而增加了GC的总时间降低吞吐量。所以需要根据实际情况设置该值。

-Xx:GCTimeRatio:设置吞吐量大小,它是一个0到100之间的整数,默认情况下他的取值是99,那么系统将花费不超过1/(1+n)的时间用于垃圾回收,也就是1/(1+99)=1%的时间。

另外还可以指定-XX:+UseAdaptiveSizePolicy打开自适应模式,在这种模式下,新生代的大小、eden、from/to的比例,以及晋升老年代的对象年龄参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。

使用-XX:+UseParallelGC参数可以设置新生代使用这个并行回收器

(二)老年代回收器:CMS、Serial Old、Parallel Old

1、SerialOld 垃圾回收器

SerialOld是Serial回收器的老年代回收器版本,它同样是一个单线程回收器。

用途

  • 一个是在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用,

  • 另一个就是作为CMS收集器的后备预案,如果CMS出现Concurrent Mode Failure,则SerialOld将作为后备收集器。

使用算法标记 - 整理算法

2、ParallelOldGC 回收器

老年代ParallelOldGC回收器也是一种多线程的回收器,和新生代的ParallelGC回收器一样,也是一种关注吞吐量的回收器,他使用了标记- 整理/压缩算法进行实现。

-XX:+UseParallelOldGc进行设置老年代使用该回收器

-XX:+ParallelGCThreads也可以设置垃圾收集时的线程数量。

3、CMS 回收器

CMS全称为:Concurrent Mark Sweep意为并发标记清除,他使用的是标记清除算法。主要关注系统停顿时间。

使用-XX:+UseConcMarkSweepGC进行设置老年代使用该回收器。

使用-XX:ConcGCThreads设置并发线程数量。

特点

CMS并不是独占的回收器,也就说CMS回收的过程中,应用程序仍然在不停的工作,又会有新的垃圾不断的产生,所以在使用CMS的过程中应该确保应用程序的内存足够可用。

CMS不会等到应用程序饱和的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置:-XX:CMSInitiatingoccupancyFraction来指定,默认为68,也就是说当老年代的空间使用率达到68%的时候,会执行CMS回收

如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行回收器;SerialOldGC进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作。

这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingoccupancyFraction的设置要根据实际的情况。

标记清除算法有个缺点就是存在内存碎片的问题,那么CMS有个参数设置-XX:+UseCMSCompactAtFullCollecion可以使CMS回收完成之后进行一次碎片整理

-XX:CMSFullGCsBeforeCompaction参数可以设置进行多少次CMS回收之后,对内存进行一次压缩

(三)全堆:G1

G1(Garbage-First)是一款面向服务器的垃圾收集器,支持新生代和老年代空间的垃圾收集,主要针对配备多核处理器及大容量内存的机器,G1最主要的设计目标是:实现可预期及可配置的STW停顿时间

1、G1分区


G1将Java堆划分为多个大小相等的独立区域(Region),每一个小方格代表一个Region,JVM最多可以有2048个Region

一般Region大小等于堆大小除以2048,比如堆大小为4096M,则Region大小为2M,当然也可以用参数-XX:G1HeapRegionSize手动指定Region大小,但是推荐默认的计算方式

1、Region

为实现大内存空间的低停顿时间的回收,将划分为多个大小相等的Region。每个小堆区都可能是 Eden区,Survivor区或者Old区,但是在同一时刻只能属于某个代

在逻辑上, 所有的Eden区和Survivor区合起来就是新生代,所有的Old区合起来就是老年代,且新生代和老年代各自的内存Region区域由G1自动控制,不断变动

2、巨型对象(Humongous区)

G1有专门分配大对象的Region叫Humongous区,而不是让大对象直接进入老年代的Region中。在G1中,大对象的判定规则就是一个大对象超过了一个Region大小的50%,比如每个Region是2M,只要一个对象超过了1M,就会被放入Humongous中,而且一个大对象如果太大,可能会横跨多个Region来存放。

作用:Humongous区专门存放短期巨型对象,不用直接进老年代,可以节约老年代的空间,避免因为老年代空间不够的GC开销

Full GC的时候除了收集年轻代和老年代之外,也会将Humongous区一并回收

2、G1 垃圾回收器工作流程

1、初始标记(Initial Marking)

这阶段仅仅只是标记GC Roots能直接关联到的对象并修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确的可用的Region中创建新对象,这阶段需要停顿线程,但是耗时很短。而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿

2、并发标记(Concurrent Marking)

从GC Roots开始对堆的对象进行可达性分析,递归扫描整个堆里的对象图,找出存活的对象,这阶段耗时较长,但是可以与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。

3、最终标记(Final Marking)

对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的 SATB 记录

4、筛选回收(Live Data Counting and Evacuation)

负责更新 Region 的统计数据,对各个 Region 的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划。可以自由选择多个Region来构成会收集,然后把回收的那一部分Region中的存活对象==复制==到空的Region中,在对那些Region进行清空

除了并发标记外,其余过程都要 STW

stop-the-world(STW)

stop-the-world会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止应用程序的执行。

当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生

3、G1垃圾收集分类

1、YoungGC

YoungGC并不是说现有的Eden区放满了就会马上触发,G1会计算下现在Eden区回收大概要多久时间,如果回收时间远远小于参数 -XX:MaxGCPauseMills 设定的值,那么增加年轻代的region,继续给新对象存放,不会马上做Young GC,直到下一次Eden区放满,G1计算回收时间接近参数 -XX:MaxGCPauseMills 设定的值,那么就会触发Young GC

G1垃圾收集器刚开始年轻代只占堆内存5%,会随着每次计算回收时间而增加,最多不超过60%

2、MixedGC【混合收集】

不是FullGC,老年代的堆占有率达到参数-XX:InitiatingHeapOccupancyPercent设定的值则触发,回收所有的年轻代和部分老年代(根据筛选回收阶段计算优先级后排序)以及大对象区,正常情况G1的垃圾收集是先做MixedGC,主要使用复制算法,需要把各个region中存活的对象拷贝到别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC

3、Full GC

停止系统程序,然后采用单线程进行标记、清理、压缩整理以空闲出来一批Region来供下一次MixedGC使用,这个过程是非常耗时的。(Shenandoah优化成多线程收集了)

(1)SerialGC

新生代内存不足发生的垃圾收集 - minor gc

老年代内存不足发生的垃圾收集 - full gc

(2)ParallelGC

新生代内存不足发生的垃圾收集 - minor gc

老年代内存不足发生的垃圾收集 - full gc

(4)CMS

新生代内存不足发生的垃圾收集 - minor gc

老年代内存不足

(5)G1 新生代内存不足发生的垃圾收集 - minor gc

老年代内存不足

4、G1和CMS的区别

1、G1从整体上来看是 标记-整理 算法,但从局部(两个Region之间)是复制算法。而CMS是 标记-清除算法。所以说,G1不会产生内存碎片,而CMS会产生内存碎片

2、CMS使用了 写后屏障来维护卡表,而G1不仅使用了写后屏障来维护卡表,还用了 写前屏障来跟踪并发时的指针变化情况(为了实现原始快照)

3、CMS对Java堆内存使用的是传统的 新生代和老年代划分方法,而G1使用的全新的划分方法

4、CMS收集器只收集老年代,可以配合新生代的Serial和ParNew收集器一起使用。G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用

5、CMS使用 增量更新解决并发标记下出现的错误标记问题,而G1使用原始快照解决

5、使用G1场景

1、50%以上的堆被存活对象占用

使用G1,就不用特意预留出很大的老年代空间,G1会根据对象存活状态,动态分配每种不同代对象需要占用的空间。

2、对象分配和晋升的速度变化非常大

前提还是大内存机器才使用G1,大内存的主机如果对象分配和晋升的速度变化非常快的话,G1的这种内存设计可以很快的划分出对应所需的区域【区域占比动态增长,不像CMS等垃圾收集器要划分固定的空间来区分年轻代和老年代】,但因为G1算法比较复杂,在小内存机器里面性能不如CMS等主流垃圾收集器。

3、垃圾回收时间特别长,超过1秒

G1有一大好处就是可以设置我们每次想要回收的停顿时间【-XX:MaxGCPauseMillis】,可以有效提升用户体验。

4、8GB以上的堆内存(建议值)

G1适合8G以上内存的机器使用【结构设计,2048个Region,内存太小的话每个Region也很小,很容易就超过Region的一半被识别为超大对象,这样Humongous区东西会很多,反而不能很好的进行GC收集】

5、停顿时间是500ms以内

和第三点类似,G1分段收集【每次不一定全部回收完所有的垃圾对象】,并且可以手动设置我们每次GC想要STW的时间

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVET提案学习:块重要性映射Block importance mapping

JVET-Y0077:AHG10: Block importance mapping 是爱立信提出的视频前处理操作,已经被集成到了VTM和HM中。 Block importance mapping需要与MCTF结合,利用MCTF中计算出的参数得到每个ctu的重要性,根据块重要性去调整每个ctu的QP。…

安装selenium

一、安装python 二、安装pycharm 三、安装selenium 安装pip install selenium 卸载pip uninstall selenium 查看pip show selenium 打开pycharm,在终端输入pip install selenium 四、安装浏览器驱动 火狐浏览器 Firefox 48 以上版本 selenium 3.x Firefox驱动(g…

用友U8.0 V10虚拟机安装教VBox + Vmware

用友ERP这个软件是我计算机生涯中最痛苦的软件了,它比C和Pytho难学很多,课上4个小时也不一定能把实验做完,所以要求课后进行一些学习和巩固。 然而,这个软件比较优秀,在新版本的计算机中安装,可能和自己电脑…

PTA 22-23-1学期《数据结构》拓展练习题集

文章目录6-1 单链表逆转6-2 逆序数据建立链表6-3 删除单链表偶数节点6-4 两个有序链表序列的合并6-5 带头结点的单链表就地逆置6-6 单链表插入排序6-7 双端队列6-8 有序数组的插入6-9 线性表元素的区间删除6-10 在一个数组中实现两个堆栈6-11 使用函数实现字符串部分复制6-12 判…

【scratch高阶案例教学】scratch斐波那契数列 scratch创意编程 少儿编程 小朋友们也可以完成如此神奇的数列

目录 scratch斐波那契数列 一、案例简介 二、案例演示 三、案例分析 1、角色分析

springmvc实现增删改查(mysql数据库)

目录 要求: 创建工程: 大致思路: 配置spring配置文件: 配置webapp下WEB-INF下的web.xml文件: 现在开始正式的写代码: dao层: service层: controller层: 整个项目源…

java web开发(编写第一个servlet程序)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 之前从来没有编写过servlet程序,更没有用tomcat部署过java web程序。所以,趁着IDEA安装好、maven配置好,开始用…

FastDFS模拟场景

新增tracker服务 模拟场景:当多个tracker同时宕机无法恢复时临时添加新的tracker是否可行 实现方案 将之前已有的tracker server的配置文件scp一份到新的机器上,并在新机器上创建store_path对应的目录依次关闭storage server服务在每个storage server中的…

作为一名前端,该如何理解Nginx?

作为一名小前端,只需要好好写代码,至于部署相关的操作,我们通常接触不到,正所谓专业的人干专业的事,我们在工作中并不需要去配置,但这并不代表不需要了解,相信大家都多多少少听过nginx&#xff…

窗口函数OVER(PARTITION BY)详细用法——语法+函数+开窗范围ROWS和RANGE

目录 一、函数写法 二、开窗的窗口范围ROWS与RANGE 1.范围限定用法 2.ROWS和RANGE的区别 (1) ROWS按行数限定 (2) RANGE按数据范围限定 order by 数字 例1 汇总数据范围为:[当前行值,当前行值3] 例2 汇总数据范围为:[当前行值-3,当前行值] o…

较多业步骤场景通用框架

我们工作的大部分时间都在写业务代码,如何写好业务代码必然是我们追求的一大目标,在编程方面,简单、易懂、可扩展性是衡量代码质量的通用标准,所以在工作中,我们能用java将产品经理的想法表达出来还不够,我…

OSCP-Vulnhub靶机记录-LordoftheRoot-walkthrough

靶机地址 https://www.vulnhub.com/entry/lord-of-the-root-101,129/ 交流学习联系:webMsec 靶机安装 主机发现 靶机ip 192.168.160.131 使用nmap扫描后发现只开放了22 ssh 尝试连接ssh 这里需要端口碰撞 再次nmap扫描 1337端口开放apache Dirsearch扫一下 404…

IS-IS 路由选择协议入门

为了理解中间系统一中间系统(IntermediateSystem-to-Intermediate System, IS-IS) 路由选择协议的本质和内在的工作原理,把它放在整个网际协议和相关技术的框架中学习是十分重要的。本章深入IS-IS协议的本质,并且探讨了国际标准化组织(Intemational Orga…

Understanding the Users and Videos by Mining a Novel Danmu Dataset

题目:Understanding the Users and Videos by Mining a Novel Danmu Dataset 作者:Guangyi Lv, Kun Zhang, Le Wu, Enhong Chen, Tong Xu, Qi Liu, and Weidong He 发表:IEEE TRANSACTIONS ON BIG DATA, 2022 切入点:弹幕交流…

C++实现二分法求零点

​目录前言 题目: 一、零点是什么? 二、二分法求零点 1.二分法 2.完整代码 总结 前言 首先,我们要清楚我们是干嘛的;其次,知道原理;最后,才能明白自己要怎么办。明确:用二分法求函数。 题目: 二分法求函数的零点: 有函数: f(x) = x5 - 15 * x4+ 85 * x3- 225 * x2…

十一、动态规划题目相关

学习来源: 代码随香炉:https://www.programmercarl.com/ labuladong算法:https://labuladong.github.io/algo/ 动态规划 动态规划五部曲 确定dp数组(dp table)以及下标的含义 确定递推公式 dp数组如何初始化 确定遍历…

炫酷的花式滑块滑动无缝切换特效

💂 个人网站:【 海拥】【小霸王游戏机】【大转盘】🤟 风趣幽默的前端学习课程:👉28个案例趣学前端💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习群】【学习文档】💬 免费且实用的计…

【ML05】Feature Scaling 特征缩放

Feature ScalingFeature Scaling 特征缩放的目的是什么Feature Scaling Method #3Dividing by maximumMean NormalizationZ-Score normalizationFeature Scaling 特征缩放的目的是什么 考虑前两个组图: 组图1:同一辆大货车拉货,同一个函数在…

Flink学习笔记(2)——Flink快速上手

目录 一、Flink快速上手 1.1、环境准备 1.2 创建项目 1.3 编写代码 1.3.1 批处理 1.3.2 流处理 1.4 本章总结 一、Flink快速上手 对 Flink 有了基本的了解后,接下来就要理论联系实际,真正上手写代码了。Flink 底层是 以 Java 编写的,…

计算机网络—物理层

计算机网络—物理层 物理层的基本概念 物理层的作用是要尽可能地屏蔽掉传输媒体和通信手段的差异,使物理层上面的数据链路层感觉不到这些差异,这样就可以使数据链路层只需要考虑如何完成本次的协议和服务,而不必考虑网络具体的传输媒体和通…