Java Heap not full but still getting error java.lang.OutOfMemoryError: Java heap space

Java Heap not full but still getting error java.lang.OutOfMemoryError: Java heap space

我的一个生产应用程序中出现了这个奇怪的问题。我已经检查了服务器上的堆 space,没有发现任何异常情况(请参见下面的屏幕),但我的应用程序执行的一些操作仍然出现以下错误。可能吗?

java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2271)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1876)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1785)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1188)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)

我怀疑问题出在代码中的列表之一,该列表将同时被近 2M 条记录填满,但仍然不确定为什么会发生这种情况,因为堆未显示已满或未达到最大使用量,但仍然出现此错误。可能吗?可能的情况是什么,有没有办法防止这种情况发生。这是生产应用程序,因此我无法共享代码。请帮帮我。

复制数组的堆栈跟踪顶部的函数似乎在开始复制之前检查它是否有足够的 space 用于整个数组。这可以解释为什么在抛出错误时堆没有被填满。正在复制的整个数组甚至可以放入堆中吗?

不一定要满了才能扔OutOfMemoryError。它必须处于当前大小加上下一个请求分配的大小超过最大值的情况。在这里,您显然复制了一个足够大的数组,分配它会触发(触发)这种情况。

来自java.lang.OutOfMemoryError

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector. OutOfMemoryError objects may be constructed by the virtual machine as if suppression were disabled and/or the stack trace was not writable.

简而言之,您尝试完成的操作需要一定数量的堆内存(创建一个包含 200 万个元素的新数组将需要大约 8-16+ 兆字节,具体取决于你的 JVM 实现),你的 JVM 说它根本没有那么多可用。您看不到可用堆之上的内存峰值,因为 JVM 在它发生之前就阻止了它的发生。

请注意,这是错误而不是异常,因此堆栈跟踪的 javadoc 的 none 没有提及它以及为什么不希望您处理它而不是检查异常。