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

2022-09-02 12:59:48

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

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

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

这不足以进一步调试
或者,如果可以通过调整以下内容来分配更多内存来修复此问题?

-Xms1024M -Xmx4096M -XX:最大项目大小=256M

更新

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

(以上似乎效果更好,继续监控)


答案 1

我怀疑您可能正在对大型索引使用排序。这是我绝对知道的一件事,对于Lucene来说,可能需要一个大的数组大小。无论哪种方式,您可能希望尝试使用以下选项使用 64 位 JVM:

-Xmx6G -XX:MaxPermSize=128M -XX:+UseCompressedOops

最后一个选项会将 64 位内存指针减少到 32 位(只要堆小于 32GB)。这通常会将内存开销减少约 40%,因此它可以帮助显著扩展内存。

更新:很可能你不需要这么大的永久发电量,当然不需要1G。你可能对128M很好,如果你使用Java 6,你会得到一个特定的错误。由于您的服务器仅限于8G,因此您可能能够以较小的perm gen获得7G的堆。要小心不要进入交换,这可能会严重减慢Java的速度。

我注意到您在更新中没有提到。如果您尚未尝试过,这可能会产生巨大的差异。您可以通过减小伊甸园的大小来挤出更多的空间,以便为终身世代提供更多空间。除此之外,我认为您只需要更多的内存或更少的排序字段。-XX:+UseCompressedOops


答案 2

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

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

解决方案是什么?

java.lang.OutOfMemoryError: 请求的数组大小超过 VM 限制可能是由于以下任一情况而出现的:

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

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

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

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


推荐