简体   繁体   English

G1GC OutOfMemory太早了

[英]G1GC OutOfMemory too early

My test code: 我的测试代码:

int SIZE = 1900;
int[][] array = new int[SIZE][];
for (int i = 0; i < SIZE; i++) {
  array[i] = new int[1024 * 1024 / 4]; // 1MB
  Thread.sleep(10);
  if (i % 100 == 0 && i != 0) {
    System.out.println(i + "Mb added");
  }
}

I launch it with arguments in java 8 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails 我在java 8 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails使用参数启动它-Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails

And it fails with OutOfMemory when only 1G is consumed. 当仅消耗1G时,它与OutOfMemory失败。

Heap
garbage-first heap   total 2097152K, used 1048100K [0x0000000080000000, 0x0000000080104000, 0x0000000100000000)
region size 1024K, 1 young (1024K), 0 survivors (0K)
Metaspace       used 3273K, capacity 4496K, committed 4864K, reserved 1056768K
class space    used 358K, capacity 388K, committed 512K, reserved 1048576K

I see that G1 allocated size is 2G and I suppose JVM is trying to allocate more and fails with OOM. 我看到G1分配的大小是2G,我想JVM正在尝试分配更多并且在OOM中失败。 But why is it trying to allocate more if half of the memory is free? 但是,如果内存的一半是免费的,为什么要分配更多呢?

With UseConcMarkSweepGC it's working fine and array was fully filled . 使用UseConcMarkSweepGC它工作正常,阵列完全填满。

I'm pretty sure this happens due to Humongous Allocations . 我很确定这是因为Humongous Allocations而发生的。
If you add this option 如果添加此选项

-XX:+PrintAdaptiveSizePolicy -XX:+ PrintAdaptiveSizePolicy

you will be able to see that most of the allocations are of 1048592 bytes which fits neither 50% nor even 100% of a single G1 region (which as seen in the output is 1024K=1048576 bytes). 您将能够看到大多数分配都是1048592字节,它不适合单个G1区域的50%甚至100%(在输出中看到的是1024K = 1048576字节)。 I assume that means that every array occupies at least two regions. 我认为这意味着每个阵列至少占据两个区域。 Since it is a humongous allocation most of the free space in the second region cannot be used. 由于它是一个巨大的分配,因此不能使用第二区域中的大部分自由空间。 This quickly causes extreme heap fragmentation making further allocations impossible. 这很快导致极端堆碎,从而无法进行进一步的分配。

Agree with @yegodm. 同意@yegodm。 Solution is to increase the Heap region with -XX:G1HeapRegionSize to make sure previous Humongous objects are no longer Humongous and will follow the regular allocation path. 解决方案是使用-XX:G1HeapRegionSize增加堆区域,以确保先前的Humongous对象不再是Humongous并且将遵循常规分配路径。 Read more about humongous object allocation here 1 在这里阅读更多关于巨大的对象分配1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM