首页 > 编程语言 >Java经典垃圾回收器介绍

Java经典垃圾回收器介绍

时间:2024-03-30 23:00:46浏览次数:26  
标签:Java 回收 XX 线程 垃圾 Serial CMS

先看总结:

垃圾回收器 分类 作用位置 使用算法 特点 适用场景
Serial 串行 新生代 复制算法 响应速度优先 适用于单CPU环境下的Client模式
ParNew 并行 新生代 复制算法 响应速度优先 多CPU环境Server模式下与CMS配合使用
Parallel 并行 新生代 复制算法 吞吐量优先 适用于后台运算而不需要太多交互的场景
Serial Old 串行 老年代 标记-压缩算法 响应速度优先 单CPU环境下的Client模式
Parallel Old 并行 老年代 标记-压缩算法 吞吐量优先 适用于后台运算而不需要太多交互的场景
CMS 并发 老年代 标记-压缩算法 响应速度优先 适用于互联网或B/S业务
G1 并行与并发 新生代、老年代 复制算法 标记-压缩算法 响应速度优先 面向服务端应用
  0    

一、垃圾回收器性能指标

  • 吞吐量:程序运行时间占总运行时间(总运行时间=程序运行时间+垃圾回收时间)的比例,垃圾回收时间越少,吞吐量越高;
  • 暂停时间:Stop Time Word (STW)的时间;
  • 内存占用:Java堆所占的大小。
以上三点构成不可能三角,即一款垃圾回收器不可能同时满足三点。随着硬件水平的提升,内存占用不再是我们关注的重点,评估垃圾回收器性能时,重点关注吞吐量和暂停时间。吞吐量和暂停时间是相互矛盾的,目前我们追求的效果是:在最大吞吐量优先的情况下,减小暂停时间。 

二、垃圾回收器组合

7款经典垃圾回收器间的组合关系:   0 说明:
  1. 两个回收器间有连线,说明它们可以搭配使用;
  2. Serial Old作为CMS出现“Concurrent Mode Failure”失败的后备预案;
  3. G1可用于新生代和老年代;
  4. 红色虚线连线:JDK 8将这两组组合声明为废弃,并在JDK 9中完全移除;
  5. 绿色虚线连线:JDK 14中,弃用了该组合;
  6. 绿色虚线边框:JDK 14中,删除了CMS。

三、经典垃圾回收器介绍

Serial、Serial Old回收器

Serial垃圾回收器为单线程串行回收器,为HotSpot中Client模式下默认的新生代垃圾回收器,采用复制算法、串行回收和STW机制进行内存回收; Serial Old垃圾回收器为Serial提供的老年代垃圾回收器,采用标记压缩算法、串行回收和STW机制进行内存回收:
  • Serial Old是运行在Client模式下默认的老年代垃圾回收器;
  • Serial Old在Server模式下主要有两个用途:与新生代的Parallel Scavenge配合使用;作为老年代CMS回收器的后备垃圾收集方案。
Serial适用于运行在Client模式下的虚拟机或者内存不大(几十MB到一两百MB)的环境下,因为是串行的,有较长时间的STW,所以并不适用于要求快响应、交互较强的应用。 可以通过XX:+UseSerialGC参数启用Serial回收器,表示新生代使用Serial,老年代使用Serial Old。

ParNew回收器

ParNew是Parallel New两个词的简写,是Serial的多线程版本垃圾回收器。ParNew是很多JVM运行在Server模式下新生代的默认垃圾回收器,采用复制算法,并行回收和STW机制进行内存回收。 可以通过XX:+UseParNewGC参数启用ParNew回收器,表示新生代使用ParNew,老年代不受影响。 Serial、ParNew搭配Serial Old回收器示意图: 0

Parallel、Parallel Old回收器

Parallel Scavenge回收器也是作用于新生代,同样采用复制算法,并行回收和STW机制。 Parallel Scavenge和ParNew对比:
  • Parallel Scavenge为吞吐量优先的垃圾回收器;
  • Parallel Scavenge具有自适应调节策略
JDK 1.6提供了用于老年代的并行垃圾回收器 —— Parallel Old回收器,用于替代Serial Old回收器。Parallel采用标记压缩、并行回收和STW机制。 可以通过-XX:+UseParallelGC指定新生代使用Parallel Scavenge回收器;-XX:+UseParallelOldGC指定老年代使用Parallel Old回收器,它们是成对存在的,开启一个另一个也会开启。 此外还可以通过-XX:ParallelGCThreads=设置并行回收器的线程数:
  • 默认情况下,当CPU数量小于8个时,-XX:ParallelGCThreads=的值等于CPU数量;
  • 当CPU数量大于8个,-XX:ParallelGCThreads=的值等于3+5*CPU_COUNT/8。
-XX:+UseAdaptiveSizePolicy 开启Parallel Scavenge的自适应调节策略:
  • 该模式下,年轻代大小、伊甸园区和幸存者区的比例、晋升老年代的对象年龄阈值都会自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。

CMS回收器

JDK 1.5 HotSpot推出了一款真正意义上的并发回收器 —— CMS(Concurrent-Mark-Sweep),第一次实现了让垃圾回收线程和用户线程同时工作。CMS的关注点在于尽可能缩短垃圾收集时用户线程停顿的时间。 CMS作为一款老年代的垃圾回收器,不能和新生代垃圾回收器Parallel Scavenge搭配使用,只能和ParNew或者Serial搭配使用。 CMS回收器示意图: 0   主要分为以下几个步骤:
  1. 初始标记(Initial-Mark):所有用户线程暂停(STW),这个阶段仅仅标记出GC Roots能直接关联到的对象,所以速度非常快,STW时间很短;
  2. 并发标记(Concurrent-Mark):该阶段从GC Roots直接关联对象开始遍历整个对象链,虽然这个过程耗时较长,但并不需要暂停用户线程,并发执行,没有STW;
  3. 重新标记(Remark):由于上一步用户线程也在执行,所以这一步用于修正因用户线程继续运行而导致标记发生变动的那一部分对象的标记记录。这个阶段会比初始标记阶段耗时长一点,但远比并发标记阶段低;
  4. 并发清除(Concurrent-Sweep):该阶段清理删除垃圾,回收空间。由于没有移动对象,所以该阶段也不需要STW。
CMS的优缺点都很明显: 优点:
  • 并发收集;
  • 低延迟。
缺点:
  • 会产生碎片。因为清理阶段用户线线程还在执行,所以只能采用不移动对象的标记-清除算法,而该算法会产生碎片问题
  • 对CPU资源敏感。CPU资源除了用于用户线程外,还需分配一部分用于处理垃圾回收,降低了吞吐量
  • 无法处理浮动垃圾。并发标记阶段,用户线程并未停止,该阶段也会产生垃圾, CMS无法对这些垃圾进行标记,只能留到下次GC时处理。
此外,CMS在回收过程中,因为用户线程并没有中断,所以还需确保用户线程有足够的内存可用。换句话说,CMS回收器不能等老年代即将被填满时才去回收,而应当堆内存使用率到达一定阈值时,便开始进行回收。如果CMS运行期间预留内存不足,就会出现一次“Concurrent Mode Failure”失败,虚拟机会启动后备方案,临时启用Serial Old回收器来完成老年代的垃圾回收。 CMS回收器可设置参数:
  • -XX:+UseConcMarkSweepGC,开启CMS GC,开启后,-XX:+UseParNewGC会自动打开;
  • -XX:CMSInitiatingOccupanyFraction=,设置堆内存使用率阈值,一旦达到这个阈值,CMS开始进行回收(JDK5及之前,默认值为68,JDK6及以上版本默认值为92%);
  • -XX:+UseCMSCompactAtFullCollection,指定在CMS回收完老年代后,对内存空间进行压缩处理,以避免碎片化问题;
  • -XX:CMSFullGCsBeforeCompaction,设置执行多少次CMS GC后,对内存空间进行压缩整理;
  • -XX:ParallelCMSThreads=,设置CMS的线程数。默认启动的线程数为(ParallelGCThreads+3)/4。我们知道,当CPU个数小于8时,ParallelGCThreads的默认值为CPU个数,所以对于一个8核CPU,默认启动的CMS线程数为3,换句话说只有62.5%的CPU资源用于处理用户线程。所以CMS不适合吞吐量要求高的场景。

G1回收器

G1(Garbage First)回收器把堆内存分割成很多不相关的区域(region,物理上不连续),使用不同区域来表示伊甸园区,幸存者区和老年代。 G1会避免对整个Java堆进行垃圾收集,它会跟踪各个region里垃圾回收的价值大小(回收所获得的空间大小及所需时间的经验值),在后台维护一个优先列表,每次根据允许收集时间,优先回收价值最大的region。 region的说明 0
  • E表示伊甸园区,S表示幸存者区、O表示老年代,空白表示未使用的内存区域;
  • 一个region在同一时间内只能属于一种角色;
  • G1新增了一个全新的内存区域——Humongous,主要用于存放大对象。
G1回收垃圾过程如下图所示:   0 主要分为以下几个步骤:
  1. 初始标记:仅仅是标记GC Roots能直接关联的对象,需要STW,但这个过程非常快;
  2. 并发标记:从GC Roots出发,对堆中对象进行可达性分析,找出存活对象,该阶段耗时较长,但是可与用户线程并发执行;
  3. 最终标记:主要修正在并发标记阶段因为用户线程继续运行而导致标记记录产生变动的那一部分对象的标记记录,需要STW;
  4. 筛选回收:将各个region分区的回收价值和成本进行排序,根据用户所期望的停顿时间制定回收计划。这阶段停顿用户线程,STW。
G1回收器的优缺点: 优点:
  • 并行与并发;
  • 分代收集,可以采用不同的算法处理不同的对象;
  • 空间整合,标记压缩算法意味着不会产生内存碎片(G1从整体来看采用标记-整理算法,从局部来看采用复制算法);
  • 可预测的停顿时间,能让使用者明确指定一个长度为M毫秒时间片段内,消耗在垃圾回收的时间不超过N毫秒(根据优先列表优先回收价值最大的region;
缺点:
  • 在小内存环境下和CMS相比没有优势,G1适合大的堆内存;
  • 在用户程序运行过程中,G1无论是为了垃圾回收产生的内存占用,还是程序运行时的额外执行负载都要比CMS高。
G1回收器相关参数设置:
  • -XX:+UseG1GC,开启G1 GC;
  • -XX:G1HeapRegionSize=,设置region的大小。值为2的幂,范围是1MB到32MB之间,目标是根据最小堆内存大小划分出约2048个区域。所以如果这个值设置为2MB,那么堆最小内存大约为4GB;
  • -XX:MaxGCPauseMillis=,设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认值为200ms;
  • -XX:ParallelGCThread=,设置STW时GC线程数值,最多设置为8;
  • -XX:ConcGCThreads=,设置并发标记的线程数,推荐值为ParallelGCThread的1/4左右;
  • -XX:InitiatingHeapOccupancyPercent=,设置触发并发GC周期的Java堆占用率阈值,超过这个值就触发GC,默认值为45。

 

 

 

 

原文链接:https://juejin.cn/post/7029155686575521828

标签:Java,回收,XX,线程,垃圾,Serial,CMS
From: https://www.cnblogs.com/MuXinu/p/18106176

相关文章

  • 【Web应用技术基础】JavaScript(1)——案例:猜数字
    因为不能插入视频,所以给大家一张一张截图的点击“重新开始一局游戏” <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0">......
  • java9到java17的新特性学习--github新项目
    ......
  • Java反射
    1.反射的基本概念Java的反射(reflection)机制是在运行状态中对于任意一个类,都能够知道这个类的所有属性和方法,反射允许对成员变量、成员方法、构造方法的信息进行编程式访问。这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。反射允许对成员......
  • Java 递归算法系列:建议收藏的 13 个经典问题的代码实现详解
    递归算法题求阶乘(Factorial)斐波那契数列(FibonacciSequence)汉诺塔(TowerofHanoi)遍历树节点(TreeTraversal)数组反转(ArrayReversal)爬楼梯问题(ClimbingStairsProblem)回文数检测(PalindromeChecking)找出数组中的最大值(FindingMaximumValueinanArray)分治算法......
  • java 项目线上拉代码,打包
    pos-admin.sh#!/bin/shecho=================================echo自动化部署脚本启动echo=================================echo停止原来运行中的工程APP_NAME=pos-admin.jar###APP_NAME=test.jar###这个地方的名称就是pom文件中的artifactId,但最好是写......
  • Java(static)
    1.在类创建完后,接下来就是创建对象,用同一个类去创建不同对象。如果用这个类去为一整个学校创建学生对象,假如有2000名学生都来自这个学校,那么开辟空间时就要为这个学校重复存储2000次,如果要进行修改,那么也要操作2000次。所以为了解决这个问题去节省内存空间,提高效率,Java提供了......
  • java来了嗷!
    题目一:Java中的重载(Overload)和重写(Override)有何区别?题目二:什么是Java中的异常处理机制?请解释try-catch-finally块的工作原理,并提供一个示例。题目三:Java中的静态方法(StaticMethod)和实例方法(InstanceMethod)有何区别?题目四:Java中的多线程(Multithreading)是如何实现的?请解释一下J......
  • java毕业设计企业人事管理系统(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着信息技术的快速发展,企业管理逐渐向数字化、智能化方向迈进。人事管理作为企业内部管理的重要组成部分,其信息化水平直接关系到企业的运行效率和管理水......
  • java毕业设计汽车零件厂绩效管理(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在现代企业管理中,绩效管理是连接企业战略目标与员工个人目标的桥梁,它对于提升员工工作积极性、优化团队协作效率以及推动企业持续发展具有重要作用。对于......
  • 使用Jep在Java中调用Conda虚拟环境下的Python
    为了解决毕设中需要用到在Java中调用Python的问题,我在网上寻找对应的解决方案。似乎没有太好的解决方案:Jython至今仍是Python2,Py4J似乎也不再活跃更新。所幸我找到了Jep这一神器。正当我雀跃不已,却又发现了一些问题,在两个小时的艰难攻关之下,这些问题逐渐迎刃而解。问题一:无法找到......