java8 matespace_metaspace元空间gc垃圾回收问题

本文讨论了Java8中遇到的Metaspace元空间垃圾回收问题,特别是在G1垃圾回收器下。内容涉及Metaspace的触发GC条件,配置参数如`MaxMetaspaceSize`和`MetaspaceSize`的影响,以及Metaspace与堆对象的关系。文章指出,元空间的GC并不直接导致Old Gen的Full GC,并建议调整配置以降低GC频率。同时,探讨了如何通过卸载类来释放元空间内存,尤其是在无`MaxMetaspaceSize`限制时的情况。

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

这是我使用jvm的g1垃圾回收在GC时遇到的问题:

2400.241: [GC concurrent-root-region-scan-start]

2400.241: [Full GC (Metadata GC Threshold) 2400.252: [GC concurrent-root-region-scan-end, 0.0101404 secs]

2400.252: [GC concurrent-mark-start]

1151M->603M(4356M), 2.6980537 secs]

[Eden: 0.0B(2558.0M)->0.0B(2613.0M) Survivors: 55.0M->0.0B Heap: 1151.7M(4356.0M)->603.6M(4356.0M)], [Metaspace: 259187K->92248K(1034240K)]

[Times: user=3.92 sys=0.00, real=2.70 secs]

这需要很长时间,每20-30分钟,metaspace就会触发一次完整的gc。

我的jvm metaspce元空间大小配置参数如下:

"-XX:MaxMetaspaceSize=768M",

"-XX:MetaspaceSize=256M"

每次它达到256M时,就会触发一次完整的full gc。

当它到达这个第一个高水位线时,它是否应该在下次达到最大内存之前使它变大?另外,metaspace上的gc会触发old gen老年代上的完整gc吗?

这使得p99的响应时间比我预期的要高。

分析原因

我的理解是元空间本身并不是每次被垃圾收集的。相反,堆中的对象包含对元空间对象的特殊引用。当GC收集对象时,相应的元空间对象将被释放。(从概念上讲,它类似于终结,终结器释放元空间对象。)

当它到达这个第一个高水位线时,它是否应该在下次达到最大尺寸之前使它变大?

显然不是。热点收集器的常规策略如下:

分配对象,直到达到当前堆限制

运行收集器

查看回收了多少空间,如果有必要,可以增加(或减少)堆大小。

这里似乎也采用了同样的策略。而完整的GC会导致足够的元空间被回收,从而决定不需要扩展元空间。

可以尝试将-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置为相同的值,但这只会降低整个GCs的频率。

1eb45ee3015f06f73be968536466964e.png

当jvm上没有设置MaxMetaspaceSize属性时,什么条件触发Metaspace的垃圾回收?

假设我关闭几个未使用的类加载器,那么就有一个作用域来释放元空间内存中的内存。我的问题是,完整的gc是触发元空间内存的清理还是以其他方式触发的?

由于java8中默认的元空间是不受限制的,jvm何时知道需要从其元空间中清除未引用的类。

元空间本身不是垃圾回收的。但是java堆是。

什么时候java.lang.Class对象被收集,底层元数据也就被释放。所以在大多数情况下,如果有任何类可以卸载,那么常规GC循环也会释放元空间。

但是想知道何时触发gc来清理未部署的应用程序的元空间内存。

最迟在元空间的当前容量已满时,也可能是在常规垃圾回收卸载类时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值