1

我用 -Xmx1024m 开始了一些 java 代码,在某些时候由于 OOM 我得到了一个 hprof。hprof 仅显示 320mb,并给我一个堆栈跟踪:

 at java.util.Arrays.copyOfRange([CII)[C (Arrays.java:3209)
  at java.lang.String.<init>([CII)V (String.java:215)
  at java.lang.StringBuilder.toString()Ljava/lang/String; (StringBuilder.java:430)
  ...

这来自我正在复制的一个大字符串。

我记得在某处读过(找不到在哪里)发生的事情是这些情况是:

  • 进程仍然没有消耗1gb的内存,远低于
  • 即使堆仍然低于 1gb,它也需要一些内存,并且copyOfRange()它必须是连续内存,所以即使它还没有超过限制,它也无法在主机上找到足够大的内存,它会失败一个OOM。

我试图寻找这方面的文档(copyOfRange()需要一块连续的内存),但找不到任何东西。

另一个可能的罪魁祸首是 permgen 内存不足。

有人可以证实或反驳连续记忆假设吗?任何指向某个文档的指针也会有所帮助。

4

1 回答 1

2

如果您使用并发标记扫描收集器,您可能会得到碎片。但是对于新对象,只要有足够的年轻代空间,您就不必担心碎片,因为空闲的伊甸园空间始终是连续的。

在许多应用程序中,只有一小部分堆给年轻代,所以如果你有一个碎片化的永久空间并且你创建了一个相对较小的对象(小到最大内存大小的 5%),你可能会得到一个 OutOfMemoryError。

鉴于如果您运行接近最大内存,您的性能将非常差,我建议您让您的应用程序使用更少的内存或增加最大值。这也会增加您的世代规模。或者你可以设置-XX:NewSize=512m

于 2011-11-29T09:46:59.803 回答