JAVA GC 分代垃圾收集过程及各种GC的特点_java series gc-程序员宅基地

技术标签: JAVA基础  

1 JVM性能相关的组件

在调优性能时,JVM的如下三个组件是重点关注的:

  • 堆:存储对象数据的地方,该区域由启动时选择的垃圾收集器管理。大多数调优选项都与堆大小设置与选择的垃圾回收器相关
  • JIT编译器:对性能也有很大的影响,但是很少需要对新版本的JVM进行调优。
  • GC【垃圾回收器】:需要根据业务,选择最适合的GC

在这里插入图片描述

2 分代垃圾收集

2.1 垃圾收集算法

常见的垃圾收集算法大致分为以下两种:引用计数法和可达性分析算法,目前虚拟机都采用可达性算法

引用计数法

基本思路:每一个对象上记录这个对象被引用的次数,只要有任何一个对象引用了次对象,这个对象的计数器就+1,取消对这个对象的引用时,计数器就-1。任何一个时刻,如果该对象的计数器为0,那么这个对象就是可以回收的。但是这种算法有个弊端:无法处理循环引用的情况,见下图

在这里插入图片描述
在栈上,在method中执行完两个set后,method方法结束,图中两条红线引用消失,可以看到留下两个对象在堆内存中循环引用,但此时已经没有地方在用他们了,造成内存泄漏。两个对象不能被GC回收

class A {
    
    private B b;
    public void setB(B b) {
    
        this.b = b;
    }
}

class B {
    
    private A a = new A();
    public void setA(A a) {
    
        this.a = a;
    }
}

public void method() {
    
    A a = new A();
    B b = new B();
    a.setB(b);
    b.setA(a);
}

可达性分析算法

在Java中,是通过可达性分析(Reachability Analysis)来判定对象是否存活的。
该算法的基本思路就是通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。
常见的GC Roots有如下几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的Native方法)引用的对象
- 被同步锁持有的对象。

在这里插入图片描述
从图上看出,对象实例1、2、4、6都具有GC Roots可达性,即存活对象,不能被GC回收。
而对于对象实例3、5虽然相互引用,但没有任何一个GC Roots与之相连,属于GC Roots不可达对象,即GC需要回收的垃圾对象。

2.2 分代垃圾收集过程

  1. 任何新对象都被分配到eden空间。两个survivor空间在启动时都是空的。
    在这里插入图片描述
  2. 当eden空间填满时,会触发一个小的垃圾收集 Young GC
    在这里插入图片描述
  3. 被引用的对象被移动到第一个survivor空间。清除eden空间后,未被引用的对象将被删除。
    在这里插入图片描述
  4. 在下一个 minor GC中,伊甸园空间也发生了同样的事情。未引用的对象被删除,引用的对象被移动到幸存者空间。但是它们被移动到第二个幸存者空间(S1)。此外,来自第一个survivor空间(S0)的上一次minor GC的对象的年龄增加并移动到S1。一旦所有幸存的对象被移动到S1, S0和eden都将被清除。注意现在在幸存者空间中有不同年龄的对象。
    在这里插入图片描述
  5. 在下一个minor GC中,重复相同的过程。然而,这一次幸存者空间切换。引用的对象被移动到S0。保存下来的对象年龄增加。eden和S1被清除。
    在这里插入图片描述
  6. 在一次minor GC之后,当老化对象达到某个年龄阈值(如8)时,它们将从年轻代提升到年老代。
    可通过如下2个参数控制对象何时提升到老年代:
    • -XX:PreternureSizeThreshold 直接晋升老年代的对象大小,设置了这个参数后,大于这个参数的对象直接在老年代进行分配。
    • -XX:MaxTenuringThreshold 晋升老年代的对象年龄,对象在每一次Minor GC后年龄增加一岁,超过这个值后进入到老年代。默认值是15。
      在这里插入图片描述
  7. 随着minor gc继续发生,对象将继续被提升到老的代空间。
    在这里插入图片描述
  8. 这几乎涵盖了年轻一代的整个过程。最后,将对老的代执行一次大的GC,以清除和压缩该空间。
    在这里插入图片描述

2.3 minor GC与major GC

在这里插入图片描述

3 垃圾回收器

3.1 Serial GC

Serial GC是JAVA 5、6中默认的GC,minor gc和 major gc都是串行完成的(使用单个虚拟CPU)。
Serial GC使用标记-压缩收集方法,此方法将旧内存移到堆的开头,以便在堆的末尾将新内存分配到单个连续内存块中。这种内存压缩使得向堆分配新内存块的速度更快。
Serial GC是最基本、历史最悠久的收集器,它是一个单线程收集器。一旦回收器开始运行时,整个系统都要停止。Client模式下默认开启,其他模式默认关闭。

在这里插入图片描述
用法:
-XX:+UseSerialGC
这个参数会使新生代和老年代都使用串行回收器,新生代使用复制算法,老年代使用标记-整理算法。

-XX:+UseParNewGC
ParNew收集器是Serial收集器的多线程版本,在新生代进行并行回收,老年代仍旧使用串行回收。新生代S区任然使用复制算法。
操作系统是多核CPU上效果明显,单核CPU建议使用串行回收器。打印GC详情时ParNew标识着使用了ParNewGC回收器。默认关闭。

3.2 Parallel GC

Parallel GC使用多个线程执行年轻代垃圾收集,是JVM中GC的默认实现,也称为吞吐量收集器。
并行收集器适用于在多处理器或多线程硬件上运行的具有中型到大型数据集的应用程序。

运行并行GC还会导致“停止世界事件”,并导致应用程序冻结,当需要完成大量工作且可以接受长时间暂停时,可以使用它,例如运行批处理作业。
在这里插入图片描述
吞吐量:CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机运行100分钟,垃圾收集花费1分钟,那吞吐量就99%

默认情况下,在具有N个cpu的主机上,并行垃圾收集器在收集中使用N个垃圾收集器线程。垃圾收集器线程的数量可以通过命令行选项来控制: -XX:ParallelGCThreads= = <所需数量>

-XX:+UseParallelGC

表示新生代使用Parallel收集器,并提供如下参数用于控制吞吐量:

  • -XX:MaxGCPauseMillis:设置最大停顿时间,值是一个大于0的毫秒数,收集器将尽力保证垃圾回收时间不超过设定值,系统运行的需要回收的垃圾总量是固定的,缩短停顿时间的同时会增大回收频度。
  • -XX:GCTimeRatio:用户控制垃圾回收时间占比,它运行的参数值是0-100的整数,如果参数设置为19,代表最大GC时间占总时间的5%(1/(1+19))。
  • -XX:UseAdaptiveSizePolicy:JVM会根据实际运行情况动态调整新生代大小、新生代和s区比例、晋升老年代对象大小等细节参数。

-XX:+UseParallelOldGC

新生代和老年代都使用并行收集器。打印出的GC会带PSYoungGen、ParOldGen关键字。
HotSpot只在老一代中进行压缩。HotSpot中的年轻一代被认为是一个拷贝收集器;因此不需要压缩。
这是自Java 7u4以来并行GC的默认版本

Compacting describes the act of moving objects in a way that there are no holes between objects. After a garbage collection sweep, there may be holes left between live objects. Compacting moves objects so that there are no remaining holes. It is possible that a garbage collector be a non-compacting collector. Therefore, the difference between a parallel collector and a parallel compacting collector could be the latter compacts the space after a garbage collection sweep. The former would not.

3.3 CMS

Concurrent Mark Sweep 并发标记清除,即使用CMS收集器 ConcMarkSweepGC
它试图通过与应用程序线程并发执行大部分垃圾收集工作来最小化由于垃圾收集而导致的暂停。通常并发低暂停收集器不会复制或压缩活动对象。垃圾收集是在不移动活动对象的情况下完成的。如果碎片成为一个问题,分配一个更大的堆。

它使用的是 标记清除算法,运作过程为四个步骤,分别是 初始标记—并发标识—重新标记—并发清除。它是老年代的收集算法,新生代使用ParNew收集算法。默认关闭

CMS的缺点对服务器CPU资源较为敏感,在并发标记时会降低吞吐量。它使用的标记清除算法也会产生大量空间碎片,空间碎片的存在会加大Full GC的频率,虽然老年代还有足够的内存,但是因为内存空间连续,不得不进行Full GC。

CMS收集器比其他gc使用更多的CPU。如果可以分配更多的CPU以获得更好的性能,那么CMS垃圾收集器是比并行收集器更好的选择。CMS GC中不执行压缩。
在这里插入图片描述

通过 -XX:+UseConcMarkSweepGC 设置使用CMS后,可以通过以下参数调整CMS的行为:

  • -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理,整理过程是独占的,会引起停顿时间变长。仅在使用CMS收集器时生效。
  • -XX:ParallelCMSThreads 设置并行GC时进行内存回收的线程数量

3.4 G1

Java 7中提供,用于替换CMS收集器。G1是一种并行、并发、递增压缩的低暂停垃圾收集器,它的布局与前面描述的其他垃圾收集器截然不同。

它像CMS一样是并行和并发的,但是它的工作原理与较老的垃圾收集器非常不同。

虽然G1也分代,但它没有针对年轻代、老年代的单独区域。相反,每个代都是一组区域,允许以灵活的方式调整年轻代的大小。

它将堆划分为一组大小相等的区域(1MB到32MB—取决于堆的大小),并使用多个线程扫描它们。在程序运行期间,一个区域可以是一个老区域,也可以是一个年轻区域。

标记阶段完成后,G1知道哪些区域包含最多的垃圾对象。如果用户对最短的暂停时间感兴趣,G1可以选择只疏散几个区域。如果用户不担心暂停时间,或者已经声明了一个相当大的暂停时间目标,G1可能会选择包含更多区域。

由于G1GC识别出垃圾最多的区域,并首先对该区域执行垃圾收集,因此它被称为Garbage First。
在这里插入图片描述
除了Eden, Survivor和Old内存区域,G1GC中还有另外两种类型的区域:

  • Humongous—用于大尺寸对象(大于堆大小的50%)
  • 可用空间-未使用或未分配的空间

使用G1垃圾收集器的JVM参数是**-XX:+UseG1GC**

3.5 Epsilon GC

Epsilon是一个不做任何事情(no-op)的垃圾收集器,作为JDK 11的一部分发布。它处理内存分配,但不实现任何实际的内存回收机制。一旦可用的Java堆耗尽,JVM就会关闭。

它可以用于超延迟敏感的应用程序,开发人员确切地知道应用程序的内存占用,甚至(几乎)拥有完全没有垃圾的应用程序。否则,不建议在任何其他场景中使用Epsilon GC。

使用Epsilon垃圾收集器的JVM参数是**-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC**.

3.6 Shenandoah GC

Shenandoah是作为JDK 12的一部分发布的一个新的GC。Shenandoah相对于G1的关键优势是,它与应用程序线程并发执行更多的垃圾收集周期工作。G1只能在应用程序暂停时清空它的堆区域,而Shenandoah可以与应用程序同时重新定位对象。

Shenandoah可以压缩活动对象,清除垃圾,并在检测到空闲内存后几乎立即将RAM释放回操作系统。由于所有这些都是在应用程序运行时并发发生的,Shenandoah是CPU密集型的

使用Epsilon垃圾收集器的JVM参数是:-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC

3.7 ZGC

ZGC是作为JDK 11的一部分发布的另一个GC,在JDK 12中得到了改进。它适用于需要低延迟(少于10毫秒的暂停)和/或使用非常大的堆(几万亿字节)的应用程序。

ZGC的主要目标是低延迟、可伸缩性和易用性。为了实现这一点,ZGC允许Java应用程序在执行所有垃圾收集操作时继续运行。默认情况下,ZGC未提交未使用的内存并将其返回给操作系统。

因此,通过提供极低的暂停时间(通常在2ms内),ZGC比其他传统gc带来了显著的改进。

Shenandoah和ZGC都计划成为产品特性,并在JDK 15中走出实验阶段

4 如何选择GC

如果应用程序没有严格的暂停时间要求,你应该只运行你的应用程序并允许JVM选择正确的收集器。
大多数情况下,默认设置应该可以正常工作。如果有必要,可以调整堆大小以提高性能。如果性能仍然不能满足您的目标,您可以根据应用程序的需求修改收集器:

GC 适用场景
Serial 如果应用程序有一个小的数据集(大约100 MB)和/或它将运行在没有暂停时间要求的单个处理器上
Parallel 如果峰值应用程序性能是优先级,并且没有暂停时间要求,或者一秒或更长时间的暂停是可以接受的
CMS/G1 如果响应时间比总体吞吐量更重要,那么垃圾收集暂停时间必须短于大约一秒
ZGC 如果响应时间具有高优先级,并且/或您正在使用一个非常大的堆

5. 配置参数

  • 获取到完整的机器名 -Djava.net.preferIPv4Stack=true
  • 打印GC日志 -Xloggc:/var/log/hive/hiveserver2-gc-%t.log -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCCause -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M
  • 打印OOM日志 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/hive/hs2_heapdump.hprof

参考

Java Garbage Collection Basics
Garbage Collection in Java – What is GC and How it Works in the JVM

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/penriver/article/details/118944545

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文