如何修复Java中"请求的数组大小超过VM限制"错误?

ajr*_*eal 17 java tomcat solr heap-memory

是否有一个日志选项可以让tomcat记录错误的查询而不是抛出这个?

SEVERE:java.lang.OutOfMemoryError:请求的数组大小超过VM限制

(尝试将日志级别设置为FULL,但仅捕获上述内容)

这还不足以进一步调试.
或者,如果可以通过调整以下内容来分配更多内存来解决这个问题?

-Xms1024M -Xmx4096M -XX:MaxPermSize = 256M

更新

-Xms6G -Xmx6G -XX:MaxPermSize = 1G -XX:PermSize = 512M

(以上看起来效果更好,继续监控)

Whi*_*g34 13

我怀疑你可能在大型索引上使用排序.这是我必须知道的一件事,Lucene需要一个大的数组大小.无论哪种方式,您可能希望尝试使用具有以下选项的64位JVM:

-Xmx6G -XX:MaxPermSize=128M -XX:+UseCompressedOops
Run Code Online (Sandbox Code Playgroud)

最后一个选项会将64位内存指针减少到32位(只要堆低于32GB).这通常会将内存开销降低约40%,因此可以显着延长内存.

更新:您很可能不需要如此庞大的永久代尺寸,当然不是1G.你可能对128M很好,如果你继续使用Java 6,你会得到一个特定的错误.由于你的服务器限制为8G,你可能能够通过7G获得更小的烫发堆根.小心不要进入交换,这会严重减慢Java的速度.

我注意到你-XX:+UseCompressedOops在更新中没有提到.如果你还没有尝试过,那可能会产生很大的不同.你可以通过减少伊甸园的大小来挤出更多的空间,给予终身一代更大的空间.除此之外,我认为你只需要更多的内存或更少的排序字段.


vaq*_*han 6

您将收到此异常,因为您正在尝试创建一个大于 Java VM 堆中最大连续内存块的数组。

https://plumbr.eu/outofmemoryerror/requested-array-size-exceeds-vm-limit

解决办法是什么?

java.lang.OutOfMemoryError: 请求的数组大小超出 VM 限制可能是以下任一情况的结果:

您的数组变得太大,最终大小介于平台限制和 Integer.MAX_INT 之间

您故意尝试分配大于 2^31-1 元素的数组来试验限制。

在第一种情况下,检查您的代码库,看看您是否真的需要那么大的数组。也许你可以减少数组的大小并完成它。或者将阵列分成更小的块,并批量加载您需要处理的数据以适应您的平台限制。

在第二种情况下——记住 Java 数组是由 int 索引的。因此,在平台内使用标准数据结构时,数组中的元素不能超过 2^31-1。事实上,在这种情况下,你已经被编译器在编译期间宣布“错误:整数太大”阻止了。但是,如果您真的使用真正的大型数据集,则需要重新考虑您的选择。您可以小批量加载您需要处理的数据,并且仍然使用标准 Java 工具,或者您可能超越标准实用程序。实现此目的的一种方法是查看 sun.misc.Unsafe 类。这允许您像在 C 中一样直接分配内存。


Art*_*tch 5

如果您想找出导致OutOfMemory的原因,您可以添加

-XX:+HeapDumpOnOutOfMemoryError 
Run Code Online (Sandbox Code Playgroud)

你的java选择.

下次内存不足时,您将获得一个堆转储文件,可以使用位于jdk/lib中的"jhat"进行分析.Jhat将向您显示堆中存在的对象以及它们消耗的内存量.


ajr*_*eal 0

将 solr 升级到较新的版本似乎可以解决此问题,可能较新的版本具有更好的堆内存管理。