Eug*_* To 5 java garbage-collection jvm g1gc
我的测试代码:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
我在java 8中使用参数启动它 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails
当仅消耗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
Run Code Online (Sandbox Code Playgroud)
我看到G1分配的大小是2G,我想JVM正在尝试分配更多并且在OOM中失败.但是,如果内存的一半是免费的,为什么要分配更多呢?
随着UseConcMarkSweepGC它的工作正常,阵列完全填满.
小智 7
我很确定这是因为Humongous Allocations而发生的.
如果添加此选项
-XX:+ PrintAdaptiveSizePolicy
您将能够看到大多数分配都是1048592字节,它不适合单个G1区域的50%甚至100%(在输出中看到的是1024K = 1048576字节).我认为这意味着每个阵列至少占据两个区域.由于它是一个巨大的分配,因此不能使用第二区域中的大部分自由空间.这很快导致极端堆碎,从而无法进行进一步的分配.