Full GC为什么那么慢?为什么老年代垃圾回收效率比新生代低很多?为什么Minor gc速度比Major GC慢?

2024-01-01 20:32

本文主要是介绍Full GC为什么那么慢?为什么老年代垃圾回收效率比新生代低很多?为什么Minor gc速度比Major GC慢?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GC类型分为三种:

Yong GC

Old GC

MIXED GC

Full GC

(有些文章和书上也叫Minor GC、Major GC、Full GC,由于Major GC的意思有些混淆,所以改成Old GC容易理解)


GC回收的“无用的类”(元数据区):
1、该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
2、加载该类的 ClassLoader已经被回收
3、该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法


JVM性能调优主要目的是避免Full GC的发生

Full GC的慢,其实是相对于Yong GC和Old GC。


Yong GC回收新生代

Old GC回收年老代,个别JVM参数配置设置了Old GC之前必须执行一次Yong GC

MIXED GC回收新生代+老年代,G1回收算法

Full GC回收新生代、老年代、元数据区/永久代


Full GC为什么那么慢?

1、元数据区的回收算法效率低,虚拟机规范Class回收条件比较苛刻


2、Full GC回收新生代、老年代、元数据区/永久代。从这个角度讲,多回收了方法区,增加了总的回收耗时。(有些文章提到Full GC能回收堆外直接内存,这个说法并不准确,本质上是JVM一个后台线程,通过虚引用遍历堆里已经被回收的对象对直接内存的直接引用,显示的调用free()方法释放直接内存,Full GC不能直接释放堆外直接内存。总之,堆外直接内存的释放,和GC方式类型无关)


3、Full GC本身不会先进行Minor GC,我们可以配置-XX:+ScavengeBeforeFullGC(非CMS回收算法)、CMSScavengeBeforeRemark(CMS回收算法)可以,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,先进行一次Minor GC可以提高老年代GC的速度。

(G1回收算法除外,G1回收有一个MIXED回收阶段,新生代和老年代都一起回收,与配置的JVM参数无关)


4、CMS发生了concurrent mode fail,young区使用ParNew(并行GC),Old+Perm(单独设置)使用CMS,整个堆(young+old+metaspace/perm)使用MSC(Mark Sweep Compact)是CMS GC算法的Full GC算法,单线程回收整个堆,回收过程有严格的步骤,碎片压缩,它是单线程的标记-压缩收集器,所以耗时非常的长。

(单线程、碎片压缩,由于并发失败,不能继续并发回收,STOP-THE-WORD回收效率是必要的,系统的内存很紧张了,好多新对象在着急的等着分配内存,不允许你再慢慢的并发回收内存,但这意味着停顿时间的大幅度增加)


5、G1发生了concurrent mode fail之后退化成了单线程回收整个堆




为什么老年代垃圾回收效率比新生代低很多?

为什么Yong GC比Old GC慢?为什么Minor gc速度比Major GC慢?

这里的Yong GC=Minor gc,Old GC=Major GC

Old GC的速度一般会比yong gc慢10倍以上


1、从并行和并发机制,并行和并发的默认线程数上,可以看出-XX:ConcGCThreads=(-XX:ParallelGCThreads + 3)/ 4

(XX:ParallelGCThreads是并行线程数,XX:ConcGCThreads是并发线程数)

(并行是STOP-THE-WORD,并发是回收垃圾的时候,应用查询继续在执行)

2、(时间换空间s1、s2)新生代复制算法比较快。Eden区回收时直接全部清空,存活的对象存放到内存容量比较小的s1,少了解决内存碎片整理  加上直接copy的速度,效率很高。


3、(新生代GC根据卡表,只需扫描部分老年代)卡表数据库结构,卡表为一个比特位的集合,卡表中每一位表示老年代4KB的空间,每一个比特位可以用来表示老年代的某一区域中的所有对象是否持有新生代对象的引用。
这样新生代GC时,可以不用花大量时间扫码所有老年代对象,来确定每一个对象的引用关系,
而可以先扫码卡表,只有卡表的标记位为1时,才需要扫码给定区域的老年代对象
而卡表位为0的锁住区域的老年代对象,一定不含有新生代对象的引用


4、(空间换时间),老年代标记清除算法会导致内存碎片化,因此就引入了标记整理算法,执行完毕后,存活的对象会按序放置,移动对象的内存地址(重点),来解决碎片化,但是执行时间较长。


5、老年代区内存容量一般较大,回收需要预留比较大的空间(老年代GC是并发执行,重新标记的时候修正引用关系),这样的话内存利用率就低(相对于新生代利用率eden+from=90%,新生代存活率低不需要预留太多内存)



这篇关于Full GC为什么那么慢?为什么老年代垃圾回收效率比新生代低很多?为什么Minor gc速度比Major GC慢?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/560434

相关文章

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

PowerShell中15个提升运维效率关键命令实战指南

《PowerShell中15个提升运维效率关键命令实战指南》作为网络安全专业人员的必备技能,PowerShell在系统管理、日志分析、威胁检测和自动化响应方面展现出强大能力,下面我们就来看看15个提升... 目录一、PowerShell在网络安全中的战略价值二、网络安全关键场景命令实战1. 系统安全基线核查

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

JVM垃圾回收机制之GC解读

《JVM垃圾回收机制之GC解读》:本文主要介绍JVM垃圾回收机制之GC,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、死亡对象的判断算法1.1 引用计数算法1.2 可达性分析算法二、垃圾回收算法2.1 标记-清除算法2.2 复制算法2.3 标记-整理算法2.4

MySQL 多表连接操作方法(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN)

《MySQL多表连接操作方法(INNERJOIN、LEFTJOIN、RIGHTJOIN、FULLOUTERJOIN)》多表连接是一种将两个或多个表中的数据组合在一起的SQL操作,通过连接,... 目录一、 什么是多表连接?二、 mysql 支持的连接类型三、 多表连接的语法四、实战示例 数据准备五、连接的性

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

Java下载文件中文文件名乱码的解决方案(文件名包含很多%)

《Java下载文件中文文件名乱码的解决方案(文件名包含很多%)》Java下载文件时,文件名中文乱码问题通常是由于编码不正确导致的,使用`URLEncoder.encode(filepath,UTF-8... 目录Java下载文件中文文件名乱码问题一般情况下,大家都是这样为了解决这个问题最终解决总结Java下