fullgc问题解决:Full GC (Metadata GC Threshold)

本文介绍了在Tomcat服务器重启或发布过程中遇到多次FullGC问题的解决过程。通过分析GC日志,发现问题根源在于Metaspace空间不足。通过调整XX:MetaspaceSize参数解决了问题,并详细解释了Metaspace的相关配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#问题描述
在工作过程中,遇到一个问题:Tomcat在重启或者发布的时候,会有多次的full GC。

笔者使用的版本说明:
Tomcat7.0.25
JDK8

首先排查JVM的问题,就要把GC日志打开

-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC

重启Tomcat服务器,发现gc日志如下:
这里写图片描述

原因描述

通过GC日志可以看到,old区离最大配置还很远,Metaspace区并没有真正释放空间,所以怀疑是Metaspace区不够用了。

以前只认为,Metaspace区是保存在本地内存中,是没有上限的,经查阅资料才发现,原来JDK8中,XX:MaxMetaspaceSize确实是没有上限的,最大容量与机器的内存有关;但是XX:MetaspaceSize是有一个默认值的:21M。问题就出在这里。
这里写图片描述

最终解决方案

既然问题找到了,那么就设置一个XX:MetaspaceSize的JVM启动参数:-XX:MetaspaceSize=128M.

Metaspace配置说明

从JDK8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。Metaspace使用的是本地内存,而不是堆内存,也就是说在默认情况下Metaspace的大小只与本地内存大小有关。当然你也可以通过以下的几个参数对Metaspace进行控制:

-XX:MetaspaceSize=N
这个参数是初始化的Metaspace大小,该值越大触发Metaspace GC的时机就越晚。随着GC的到来,虚拟机会根据实际情况调控Metaspace的大小,可能增加上线也可能降低。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用java -XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:Metaspacesize21810376B(大约20.8M)。
在这里插入图片描述
-XX:MaxMetaspaceSize=N
这个参数用于限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。在本机上该参数的默认值为4294967295B(大约4096MB)。

-XX:MinMetaspaceFreeRatio=N
当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增长Metaspace的大小。在本机该参数的默认值为40,也就是40%。设置该参数可以控制Metaspace的增长的速度,太小的值会导致Metaspace增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而太大的值会导致Metaspace增长的过快,浪费内存。

-XX:MaxMetasaceFreeRatio=N
当进行过Metaspace GC之后, 会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放Metaspace的部分空间。在本机该参数的默认值为70,也就是70%。

-XX:MaxMetaspaceExpansion=N
Metaspace增长时的最大幅度。在本机上该参数的默认值为5452592B(大约为5MB)。

-XX:MinMetaspaceExpansion=N
Metaspace增长时的最小幅度。在本机上该参数的默认值为340784B(大约330KB为)。

参考资料

第一次FullGC优化实战
JVM之永久区Permanent区参数设置分析
Metaspace

<think>好的,用户想了解GC日志中Full GC频繁出现的原因以及相关的日志类型。首先,我需要回忆一下JVM的垃圾回收机制,特别是Full GC发生的条件和可能的原因。 根据引用[3]和[4],Full GC通常涉及整个堆的回收,包括老年代、元空间等。频繁的Full GC可能由内存泄漏、对象过早晋升或者元空间配置不当引起。比如,如果元空间的大小设置不合理,达到阈值就会触发Full GC,如引用[4]提到的MetaspaceSize参数设置问题。 接下来,用户提到的日志类型需要区分不同的GC事件。例如,Full GC(Metadata GC Threshold)可能表示元空间不足,而Full GC(Allocation Failure)则可能是堆内存不足。需要结合具体的日志信息来分析,引用[3]中的例子说明了这一点。 然后,我应该整理可能的原因,包括内存分配问题、代码层面的问题JVM参数配置不当等。例如,大对象分配可能导致老年代直接被填满,或者Young区过小导致对象提前晋升到老年代,引用[3]中的ParOldGen部分可能与此相关。 在分析步骤方面,用户需要检查GC日志中的触发原因、内存变化趋势以及各区域的使用情况。引用[1]提到的工具如jstat和GCViewer可以帮助可视化分析。此外,优化方法需要根据原因来调整参数,比如增大堆大小、调整元空间配置或优化代码逻辑,如引用[4]中建议设置MetaspaceSize和MaxMetaspaceSize相同。 最后,用户可能需要相关的扩展问题,比如如何监控GC活动或具体的调优案例,这可以引导他们进一步学习。需要确保回答结构清晰,引用相关的参考资料,如引用[1]到[4]中的内容,来支持分析。</think>### GC日志中Full GC频繁出现的原因分析及调优方法 #### 一、Full GC触发机制与日志特征 Full GC指对**整个堆内存(Young区、Old区、Metaspace)**进行全面回收的垃圾回收行为。在GC日志中,Full GC的典型标识为: - 触发原因标记:例如 `Full GC (Metadata GC Threshold)` 表示元空间达到阈值[^3][^4] - 内存区域变化:如 `PSYoungGen`(年轻代)、`ParOldGen`(老年代)、`Metaspace`(元空间)的回收记录 #### 二、高频Full GC的常见原因 1. **内存分配问题** - **大对象直接进入老年代**:未经过Young GC的大对象直接分配在老年代,导致Old区快速填满 - **Young区过小**:对象过早晋升到Old区(可通过`-XX:MaxTenuringThreshold`参数调整晋升阈值) 2. **代码层面问题** - **内存泄漏**:长时间持有无用对象引用(如静态集合未清理) - **频繁创建大对象**:如未复用的大型数组或集合 3. **JVM参数配置问题** - **元空间配置不当**:未设置`-XX:MetaspaceSize`和`-XX:MaxMetaspaceSize`导致频繁扩容触发Full GC - **堆内存不足**:总堆大小(`-Xmx`)设置过小 #### 三、日志分析方法 1. **检查触发原因标记** ```log [Full GC (Metadata GC Threshold) ...] //元空间触发 [Full GC (Allocation Failure) ...] //堆内存不足触发 ``` 2. **观察内存变化趋势** - 使用`GCViewer`工具分析日志: ```bash java -jar gcviewer_1.3.4.jar gc.log ``` 关注**Old区内存回收效果**,若回收后内存占用仍持续增长,可能存在内存泄漏[^1] 3. **各区域使用率分析** - **Metaspace**:检查是否频繁接近`MaxMetaspaceSize` - **Old区**:观察每次Full GC后的剩余空间是否持续增加 #### 四、调优方案 | 问题类型 | 优化方法 | |-----------------|--------------------------------------------------------------------------| | 元空间问题 | 设置`-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M`[^4] | | 内存泄漏 | 使用`jmap -histo:live <pid>`查找大对象,结合代码审查 | | 晋升过早 | 增大Young区(`-Xmn`),调整`-XX:MaxTenuringThreshold` | | 堆内存不足 | 增大总堆大小(`-Xmx`与`-Xms`),建议设置为物理内存的1/4~1/2 | #### 五、性能监控工具推荐 1. **实时监控**:`jstat -gc <pid> 1000`(每秒输出GC数据)[^1] 2. **可视化分析**:`VisualVM` + Visual GC插件(开发环境适用)[^1] 3. **生产环境方案**:`Prometheus` + `Grafana`监控体系[^1]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐崇拜234

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值