Java 元空间 Full GC

标签 java garbage-collection g1gc

我在使用 G1GC 时遇到一些问题。

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 分钟就会触发一次完整的垃圾回收。 我是这样配置的:

  "-XX:MaxMetaspaceSize=768M",
  "-XX:MetaspaceSize=256M"

但是每次达到256M~就会触发一次full gc。当它达到第一个高水位线时,它不应该在下一次将其变大直到最大尺寸吗? 另外,元空间上的完整GC会触发旧一代上的完整GC吗?我在某处读到过,但我不确定。 这使得 p99 响应时间比我预期的要长。

最佳答案

根据Triggering of gc on Metaspace memory in java 8 ,需要完整的GC以减少元空间的使用。

我的理解是,元空间本身并不是垃圾收集的。。相反,普通堆中的对象保存对元空间对象的特殊引用。当对象被GC收集时,相应的元空间对象被释放。 (从概念上讲,这就像终结器,其中终结器释放 - 元空间对象。)

When it reach this first high-water-mark should not it make it bigger next time until the max size?

显然不是。 HotSpot收集器的正常策略是这样的:

  1. 分配对象,直到达到当前堆限制
  2. 运行收集器
  3. 查看回收了多少空间,并在必要时增加(或减少)堆大小。

看来这里也使用了同样的策略。完整的 GC 导致足够的元空间被回收,因此它决定不需要扩展元空间。

对此的一个创可贴是尝试将 -XX:MetaspaceSize-XX:MaxMetaspaceSize 设置为相同的值,但这只会导致完整的 GC频率较低。

真正的解决方案是找出消耗元空间的内容并修复它。

关于Java 元空间 Full GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53101801/

相关文章:

java - java中的偏向锁定

Android 垃圾收集器在我的应用程序中努力工作

Java NIO SelectionKey.attachment() 在取消时释放

c++ - 垃圾收集的概念与非 OOP 语言有何关系

java - JVM GC 工作很奇怪

java - G1 比 Java 7 上的默认垃圾收集器慢

java.lang.NullPointerException 和结果集

java - 基本 SQLite 应用程序抛出运行时异常

java - 为什么我提高内存时更频繁地获得 GC?

java - Java 应用程序的 XML 配置文件中的 ${some.thing} 是什么