一次 JVM FullGC 的排查过程及解决方案!

记一次频繁fullgc排查到解决全流程复盘 阿里云oss文件上传导致的频繁fullgc问题排查到解决全流程复盘 阅读详情

1、问题产生

最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示:

看到GC日志,我第一时间关注到的不是GC耗时,而是GC触发的原因:Metadata GC Threshold

也就是 FullGC 触发的原因是因为Metaspace大小达到了GC阈值。在监控系统里面看了一下Metaspace的大小变化趋势,如下图所示:

按照以往的经验,Metaspace在系统稳定运行一段时间后占用空间应该比较稳定才对,但是从上图来看,Metaspace显然是呈现大幅波动。为什么呢?

2、相关知识

我们知道Metaspace主要存储类的元数据,比如我们加载了一个类,那么这个类的信息就会按照一定的数据结构存储在Metaspace中。

Metaspace的大小和加载类的数目有很大关系,加载的类越多,Metaspace占用内存也就越大。

Metaspace被分配于堆外空间,默认最大空间只受限于系统物理内存。跟它相关的比较重要的两个JVM参数:

-XX:MetaspaceSize -XX:MaxMetaspaceSize

MaxMetaspaceSize,大家从名字也能猜到是指Metaspace最大值。

而MetaspaceSize可能就比较容易让人误解为是Metaspace的最小值,其实它是指Metaspace扩容时触发FullGC的初始化阈值。

在GC后Metaspace会被动态调整:如果本次GC释放了大量空间,那么就适当降低该值,如果释放的空间较小则适当提高该值,当然它的值不会大于MaxMetaspaceSize.

另外一个相关知识是:Metaspace中的类需要满足什么条件才能够被当成垃圾被卸载回收?

条件还是比较严苛的,需同时满足如下三个条件的类才会被卸载:

  • 该类所有的实例都已经被回收;

  • 加载该类的ClassLoader已经被回收;

  • 该类对应的java.lang.Class对象没有任何地方被引用。

3、排查过程

我们可以回过头再细看GC日志,可以看出Metaspace已使用内存在FullGC后明显变小(372620K -> 158348K),说明Metaspace经过FGC后卸载了很多类。

从这点来看,我们有理由怀疑系统可能在频繁地生成大量”一次性“的类,导致Metaspace所占用空间不断增长,增长到GC阈值后触发FGC。

那么这些被回收的类是什么呢?

为了弄清楚这点,我增加了如下两个JVM启动参数来观察类的加载、卸载信息:

-XX:TraceClassLoading -XX:TraceClassUnloading

加了这两个参数后,系统跑了一段时间,从Tomcat的catalina.out日志中发现大量如下的日志:

 

到此基本可以确定Metaspace增长的元凶是这些类,那么这些类

sun.reflect.GeneratedSerializationConstructorAccessorXXX

是干嘛的呢?又是从哪里引进来的呢?我也是一脸懵逼~~ 

根据类名Google了一把,找到了@寒泉子写的《从一起GC血案谈到反射原理》,这篇文章对这些类的来源解释得很透彻。在这里我简单总结如下:

Method method = XXX.class.getDeclaredMethod(xx,xx);method.invoke(target,params);

这些类的来源是反射,类似上面所示的反射代码应该大家都写过或者看过,我们常用的大多数框架比如Spring、Dubbo等都大量使用反射。

出于性能的考虑,JVM会在反射代码执行一定次数后,通过动态生成一些类来将”反射调用”变为“非反射调用”,以达到性能更好。而这些动态生成的类的实例是通过软引用SoftReference来引用的。

我们知道,一个对象只有软引用SoftReference,如果内存空间不足,就会回收这些对象的内存;如果内存空间足够,垃圾回收器不会回收它。只要垃圾回收器没有回收它,该对象就可以被使用。

那么,究竟在什么时候会被回收呢?

SoftReference中有一个全局变量clock代表最后一次GC的时间点,有一个属性timestamp,每次访问SoftReference时,会将timestamp其设置为clock值。

当GC发生时,以下几个因素影响SoftReference引用的对象是否被回收:

  • SoftReference对象实例多久未访问,通过clock - timestamp得出对象大概有多久未访问;

  • 内存空闲空间的大小;

  • SoftRefLRUPolicyMSPerMB常量值;

是否保留SoftReference引用对象的判断参考表达式,true为不回收,false为回收:

clock - timestamp <= freespace * SoftRefLRUPolicyMSPerMB

4、说明

  • clock - timestamp:最后一次GC时间和SoftReference对象实例timestamp的属性的差。就是这个SoftReference引用对象大概有多久未访问过了

  • freespace:JVMHeap中空闲空间大小,单位为MB。

  • SoftRefLRUPolicyMSPerMB:每1M空闲空间可保持的SoftReference对象生存的时长(单位ms)。这个参数就是一个常量,默认值1000,可以通过参数:-XX:SoftRefLRUPolicyMSPerMB进行设置。

查看了一下我们系统的JVM参数配置,发现我们把SoftRefLRUPolicyMSPerMB设置为0了,这样就导致软引用对象很快就被回收了。进而导致需要频繁重新生成这些动态类。

为了验证这个猜测,我把SoftRefLRUPolicyMSPerMB改成了6000进行观察,发现果然猜得没错。

系统启动后不久Metaspace的使用空间基本保持不变了,运行几天后也没再出现因为Metaspace大小达到阈值而触发FGC。至此问题解决。

 

Full GC 排查的方式有哪些? Full GC(Full Garbage Collection) 是 Java 虚拟机(JVM)中的一种垃圾回收机制,它会清理整个堆内存(包括新生代和老年代),通常会导致应用程序暂停(Stop-The-World)。Full GC 的频繁发生会严重影响系统性能,因此需要及时排查和优化。以下是排查 Full GC 的常见方式:使用监控工具可以实时观察 JVM 的内存使用情况和 GC 行为。jstat: 关键指标: :Full GC 次数。 :Full GC 总耗时。 :GC 总耗时。 jmap: 阅读详情

相关推荐

一次线上JVM调优实践,FullGC40次/天到10天一次的优化过程

对于JVM垃圾回收,之前一直都是处于理论阶段,就知道新生代,老年代的晋升关系,这些知识仅够应付面试使用的。前一段时间,线上服务器的FullGC非常频繁,平均一天40多次,而且隔几天就有服务器自动重启了,这表明的服务器的状态已经非常不正常了,得到这么好的机会,当然要主动请求进行调优了。未调优前的服务器GC数据,FullGC非常频繁。 首先服务器的配置非常一般(2核4G),总共4台服务器集群。每...

believer123的专栏 3万+

FullGC

FullGC

u014644574的博客 1万+

纯干货:线上出现fullGC次数很多的排查思路以及实践总结

最近线上发布了一个版本,导致full gc次数忽然就上去了,虽然对线上业务造成的影响还不是很大,但是为了以防万一还是对这个问题做了相关排查。 GC命令排查 一开始还是从堆的变化开始: # 查看每秒的堆发生的变化以及gc的次数 jstat -gcutil pid 1000 相关参数: s0 : Heap上的 Survivor space 0 区已使用空间的百分比 s1 : Heap上的 S...

长沙要起风了、 7386

GC原理详解

GC就是Java的垃圾回收机制,要了解什么情况下会发生GC(即GC得触发条件),我们需要先了解JVM的内存模型结构,之前一篇文章已经详细讲解了Jvm的内存模型结构,而通常来说,GC主要针对的是堆(java heap)区。 而java heap是分代的(年轻代和老年代),为什么要分代?其实也不难理解,分代就是为了优化性能,如果不分代,那就会导致所有对象揉在一块,那样GC就会对堆区域进行全扫描。所以,分代可以大大提升GC性能,那么,分代的原理是什么? JVM对于堆的垃圾回收,采用分代收集的策略,所以分代的原

Likes的博客 5426

一次频繁Full GC的排查过程

问题描述最近公司的线上监控系统给我推送了一些kafka lag持续增长的消息,我上生产环境去看了相应的consumer的情况,发现几台机器虽然还在处理消息,但是速度明显慢了很多。问题猜测与验证我猜测是JVM频繁做Full GC,导致进程也跟着频繁卡顿,处理消息的速度自然就慢了。为了验证这个想法,先用jstat看看内存使用情况: jstat -gcutil 1 1000 #1是进程号 结果如我所

沈鸿斌的博客 1万+

什么情况会发生Full GC?如何避免频繁Full GC?

Full GC(Full Garbage Collection)是Java虚拟机中进行垃圾回收的一种操作,它的目标是清理整个Java堆内存,包括年轻代(Young Generation)、年老代(Old Generation或Tenured Generation)、以及永久代(在Java 8及之前的版本中,而在Java 8及之后的版本中由Metaspace取代,所以这里可以理解为元空间Metaspace)。

BUG指挥课堂 2374

一次 JVM FullGC 的排查过程及解决方案!

本文来源:字节观,是二阿公同学的投稿问题产生最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示:看到GC日志,我第一时间关注到的...

石杉的架构笔记 1496

【四季发财中线】通达信炒股指标副图指标使用图文教程,短线紫色柱线操作,与中线短柱线共振抓牛股妖股主升浪

如上图标记位置,对应的是副图指标的紫色柱线开始的位置,这个紫色柱线信号开始出现,也是短线进场做多的信号,紫色柱线的持续出现和加长,可以持股待涨,或行情继续上涨的可以在分时行情中逢低进场短线顺势做多。如上图标记部分,指标的主要部分信号,三行柱线-ZR-ZC -ZM,当出现这三行信号时,中线或波段看多做多,信号持续则中线顺势做多和持股待涨。不论是跟踪信号的出现先后进场和持股,或是在中线多头的行情中,找到短线转多信号进场做安全的短线操作机会,都是非常好的指标信号和辅助操作功能。

weixin_69760830的博客 1602

一次 JVM FullGC 的排查过程及解决方案!(Metadata GC Threshold)

一次 JVM FullGC 的排查过程及解决方案! 本文来源:字节观,是二阿公同学的投稿 问题产生 最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示: 看到GC日志,我第一时间关注到的不是GC耗时,而是GC触发的原因:Metadata GC Threshold 也就是 FullGC 触发的原因是因为Metaspace大小达到了GC阈值。在监控系统里面看了一下Metaspace的大小变化趋势,如下图所示: 按照以往的经验,Metaspace在系统

八荒六合唯我独尊 6329

MATLAB 2026最新版免费下载安装教程:许可证激活与报错排查

科学计算与仿真在工程实践中扮演着核心角色,MATLAB 作为业界标准平台,凭借矩阵运算、数据可视化和 Simulink 仿真能力,成为高校课程设计与科研实验中的高频工具。理解其许可证机制是正确安装与持续使用的关键:官方提供试用版、学生版、家庭版及校园许可证等多种合法获取途径,安装包由引导器、工具箱文件与授权信息组成。掌握从下载到激活的完整流程,并根据操作系统进行环境配置与工具组件选装,不仅能规避安全风险,还能显著提升工程效率。针对安装过程中常见的许可证校验失败或工具箱不可用等问题,提供系统化排查思路与命令行

weixin_30702441的博客 2652

英飞凌TC3xx DSADC旋变软解码实战:从示波器波形到VX1000数据,手把手教你避坑

本文详细介绍了英飞凌TC3xx系列微控制器的DSADC模块在电机旋变软解码中的实战应用。从示波器波形分析到VX1000数据采集,提供了一套完整的调试方法论,帮助工程师快速定位和解决常见问题,提升解码精度和系统性能。

weixin_30598225的博客 517

一次 JVM FullGC 的排查过程及解决方案!---字节观

问题产生 最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示: 看到GC日志,我第一时间关注到的不是GC耗时,而是GC触发的原因:Metadata GC Threshold 也就是 FullGC 触发的原因是因为Metaspace大小达到了GC阈值。在监控系统里面看了一下Metaspace的大小变化趋势,如下图所示:...

weixin_33694620的博客 307

OpenSees入门指南:从零开始的环境配置与TCL脚本实战

本文提供了一份详细的OpenSees入门指南,涵盖从零开始的环境配置到TCL脚本实战的全过程。文章重点讲解了OpenSees的安装步骤、环境变量设置,并推荐了高效的VS Code集成开发环境配置方法。通过一个简支梁分析的完整TCL脚本示例,手把手引导读者完成第一个非线性有限元分析,帮助土木工程与结构工程领域的研究者与学生快速上手这一强大的开源分析工具。

weixin_28829339的博客 336

记一次FullGC排查过程

因为使用占用到100%,就很明显了。

八角塘塘主的博客 2974

华为OD机试真题 新系统2026-04-08 Python&JS 实现【配置操作失败数量统计】

模拟一个系统的命令行配置,包含添加、修改、删除三项操作,详情如下: 添加操作命令:add_rulerule_id=1rule_index = 18 修改操作命令: mod_rule rule_id= 1rule_index = 100 删除操作命令:del_rulerule_id=1

MISAYAONE的博客 586

Rerender A Video 技术浅析(四):跨帧约束

时间一致性是指在视频处理过程中,保持相邻帧之间内容、风格和运动的平滑过渡,避免出现视觉上的不连续性或伪影。时间一致性跨帧约束模块的主要目标是在视频增强、风格迁移等任务中,确保处理后的视频在时间维度上保持一致性和稳定性。该模块主要通过以下几种方式实现时间一致性:1.时序损失(Temporal Loss):最小化相邻帧之间的差异,确保帧间内容的平滑过渡。2.循环一致性损失(Cycle Consistency Loss):确保帧间转换的一致性,避免出现风格漂移。3.

m0_75253143的博客 1481

一次JVM中FullGC问题排查过程

这个问题比较常见,我把过程中的日志记录下来了,希望后续大家遇到类似的能快速定位。 1、平均三秒一次FullFC  sudo -u admin java/bin/jstat -gcutil `pgrep java -u admin` 1000 2000   S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

iamzhongyong的专栏 1671

2025届程序技术类笔试题

希尔排序在直接插入排序的基础上进行了改进,它通过比较相距一定间隔的元素来进行,各轮比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一轮排序为止。某人逆着水流的方向向岸边划船,每次行进前进x米后需要休息一下,休息期间船会自行倒退y米,每次休息后再次行进,前进距离缩短1/5,若起始距离岸边为m米,问:能否到达岸上,需要行进多少次才能上岸。直接插入排序的原理是将第i个元素插入前面i-1个已排好序的记录中,将比第i个元素大的记录依次向后移动一个位置,将第i个元素插入空位。第二轮相邻比较,后移2次。

博客 597

(转)一次 JVM FullGC 的排查过程及解决方案

转自 石杉的架构笔记 一篇不错的JVM FullGC定位分析 问题产生 最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示: 看到GC日志,我第一时间关注到的不是GC耗时,而是GC触发的原因:Metadata GC Threshold 也就是 FullGC 触发的原因是因为Metaspace大小达到了GC阈值。在监控系统里面看了一下Meta...

简易开头 快速迭代 519

YOLO26改进策略【Neck】| ICCV2025 反向卷积 Converse2D 数学逆运算提重构 + 特征域建模降伪影,提升多尺度目标检测精度

本文记录的是利用Converse2D 算子改进 YOLO26 的上采样。(Converse 2D Convolution)通过正则化最小二乘闭式解与深度化空间建模结合,实现YOLO26特征提取与上采样阶段的卷积逆运算及特征精准重构。本文利用算子,通过闭式解的非迭代计算还原卷积下采样后的原始特征,再通过可学习核与自适应正则化参数稳定逆问题求解,同时依托圆形填充与插值初始估计保留特征高频细节,对YOLO26中不同尺度检测目标的特征进行针对性重构强化、抑制卷积/转置卷积带来的伪影与信息损失干扰,在特征融合与上采样

Limiiiing的博客 655

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

记一次排查线上频繁FullGC 过程

记一次排查线上频繁FullGC 过程一、一段艰辛的排查过程1.突发告警1.1 新生代老年代情况:1.2 老年代GC情况2.紧急处理3.问题定位3.1 dump文件过大:3.2 如何分析:3.3 排查原因3.4 水落石出4.修复上线二、收获 一、一段艰辛的排查过程 记录一次生产环境频繁FullGC的排查过程,艰辛但收获满满; 1.突发告警 这是一个风和日丽的下午,已经疲惫不堪的我正日常码代码,突然收到JVM监控告警,进入监控大盘查看JVM情况: 1.1 新生代老年代情况: 图片截了一张最简化的出来,因为公司

shixiaoling123的博客 744

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: JAVA三种遍历机制的性能比较
下一篇: 一文解析总结Java虚拟机内存区域模型
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值