首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >G1GC OutOfMemory太早了

G1GC OutOfMemory太早了
EN

Stack Overflow用户
提问于 2017-08-29 12:51:19
回答 2查看 2.2K关注 0票数 6

我的测试代码:

代码语言:javascript
复制
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");
  }
}

我使用java 8 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails中的参数启动它。

当只消耗1G时,它就会在OutOfMemory上失败。

代码语言:javascript
复制
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

我看到G1分配的大小是2G,我认为JVM正在尝试分配更多的OOM,但是在OOM中失败了。但是,如果一半的内存是空闲的,它为什么要分配更多的内存呢?

有了UseConcMarkSweepGC,它工作得很好,数组也完全填满了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-29 15:11:29

我很确定这是大额拨款造成的。

如果添加此选项

-XX:+PrintAdaptiveSizePolicy

您将可以看到,大多数分配都是1048592字节,这既不适合单个G1区域的50%,甚至也不适合100% (在输出中看到的是1024K=1048576字节)。我认为这意味着每个数组至少占据两个区域。由于这是一个庞大的分配,第二个区域的大部分自由空间不能使用。这很快会导致极端的堆碎片,使进一步的分配无法进行。

票数 8
EN

Stack Overflow用户

发布于 2017-08-30 12:14:54

同意@yegodm。解决方案是使用-XX:G1HeapRegionSize增加堆区域,以确保以前的大型对象不再庞大,并将遵循常规的分配路径。在这里阅读更多关于大型对象分配的信息(1)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45939678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档