Java 尽管有 -Xmx10G,但 GC 仍启动了大约 2.5GB

Java GC kicks in around 2.5GB despite -Xmx10G

我有一个关于 Java 大堆大小的垃圾收集的问题。

当我在 64 位 windows 和 64 位 JDK (java8u72) 上执行我的 Java 程序时:

java -Xmx10G -Xms6G -verbose:gc <Class>

然后:

首先,这是什么意思?这个2766094K是heap utilization(2.7G)之前,然后是239630(2.3G)之后,然后是6647808K(6G)堆大小,对吗?

为什么当我请求 10 GB 的最大堆时 GC 启动大约 2.5G?如何解决这个问题?

我的笔记本电脑有 8 GB 物理 RAM,但我假设更大的堆大小由虚拟内存处理并且对 VM 透明!?

发送

一个可能的原因可能是您试图分配一大块内存(例如,一个大数组,可能通过 ArrayList)。有足够的free space 总共 不足以为大数组分配内存,free space 也需要不间断(你需要一块内存这些都是免费的,至少和你的阵列一样大。

例如,如果您尝试创建一个大小为 5 的数组,并且您在 3、3 和 2 块中有空闲内存,Java 仍然需要执行 GC,即使您有 8 个空闲单元总内存。

  1. 6647808K (6G) 是年轻代的堆大小。它不是实际的堆大小。
  2. 由于堆大小分为新生代和老年代,新生代和老年代的比例通常为1:8。因此,其余 4 GB 分配给老一代。 JVM在young gen分配内存失败,gas发起minor GC,所以young gen的对象大小为2766094K,minor GC后内存大小变为239630K。

检查 Full GC 何时执行。就像下面这样 -

[Full GC(元数据 GC 阈值)[PSYoungGen:11605K->0K(150016K)] [ParOldGen:27075K->32787K(87040K)] 38681K->32787K(237056K),[元空间:19481K->19481K (1067008K)], 0.0989447 秒] [时间: user=0.33 sys=0.00, real=0.10 secs]