metaspace gc 案例
这是我使用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的频率。
可以参考这篇文章介绍:https://javakk.com/369.html
当jvm上没有设置MaxMetaspaceSize属性时,什么条件触发Metaspace的垃圾回收?
假设我关闭几个未使用的类加载器,那么就有一个作用域来释放元空间内存中的内存。我的问题是,完整的gc是触发元空间内存的清理还是以其他方式触发的?
由于java8中默认的元空间是不受限制的,jvm何时知道需要从其元空间中清除未引用的类。
元空间本身不是垃圾回收的。但是java堆是。
什么时候java.lang.Class对象被收集,底层元数据也就被释放。所以在大多数情况下,如果有任何类可以卸载,那么常规GC循环也会释放元空间。
但是想知道何时触发gc来清理未部署的应用程序的元空间内存。
最迟在元空间的当前容量已满时,也可能是在常规垃圾回收卸载类时。
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/378.html
暂无评论