G1 不允许分配大对象,而 Parallel 允许

G1 does not allow to allocate large object while Parallel does

openjdk 11.0.14.1 2022-02-08

考虑以下简单的 Java 程序。

public static void main( String[] args ){
    int i[] = new int[Integer.MAX_VALUE / 2];
}

此处 int 的大小为 4 字节,因此分配 int[Integer.MAX_VALUE / 2] 需要 4G 的空闲堆大小。现在让我们 运行 具有不同选项的程序。

我. -XX:+UseParallelGC -Xmx5g

结果OutOfMemoryError.

崩溃

尽管堆大小足够大。很明显 -XX:NewSize 默认情况下是 1310 MB 并且 Old generation 不够大。

II. -XX:+UseParallelGC -Xmx5g -XX:MaxNewSize=128m -XX:NewSize=128m

结果:正常完成

应用程序 运行 很好,因为老一代足够大,可以容纳数组分配。

现在让我们将收集器从 Parallel 更改为 G1

III. -XX:+UseG1GC -Xmx5g -XX:MaxNewSize=128m -XX:NewSize=128m

结果: 使用 OutOfMemoryError 崩溃。

这是我不知道的。我认为调整 -XX:G1HeapWastePercent 会有帮助,但没有。

为什么G1 无法保留数组的分配以及调整哪些选项以修复它?

这是一个 JVM 错误 JDK-8279241“G1 Full GC 并不总是将内存滑动到底部地址”。应该在JDK19.

解决

解决方法是禁用 Class 数据共享。测试不会因 -Xshare:off

而失败