序列化期间堆空间不足 [英] Out of heap space during serialization
问题描述
以下代码导致大约300万行的OutOfMemmoryError: heap space
.
The following code is causing a OutOfMemmoryError: heap space
for some 3 million rows.
使用64位安装,分配给JVM的内存为4 GB.
Memory allocated to JVM is 4 GB, using 64 bit installation.
while (rs.next())
{
ArrayList<String> arrayList = new ArrayList<String>();
for (int i = 1; i <= columnCount; i++)
{
arrayList.add(rs.getString(i));
}
objOS.writeObject(arrayList);
}
ArrayList
引用的内存在while循环的每次迭代中都可以进行垃圾回收,并且由于堆空间的原因,JVM内部会在抛出OutOfMemoryError
之前在内部调用垃圾回收(System.gc()
).
The memory referenced by the ArrayList
is eligible for garbage collection in each iteration of the while loop, and internally JVM calls garbage collection (System.gc()
) before throwing an OutOfMemoryError
because of heap space.
那为什么会发生异常?
推荐答案
objOS
是ObjectOutputStream
吗?
如果是这样,那就是您的问题:ObjectOutputStream
强烈引用曾经写入过的每个对象,以避免重复写入同一对象(它只会写一个引用说我之前写过的ID为 x 的那个对象").
If so, then that's your problem: An ObjectOutputStream
keeps a strong reference to every object that was ever written to it in order to avoid writing the same object twice (it will simply write a reference saying "that object that I wrote before with id x").
这意味着您实际上在泄漏所有 ArrayList
个项目.
This means that you're effectively leaking all ArrayList
istances.
您可以通过调用 reset()
在您的ObjectOutputStream
上.由于无论如何在writeObject
调用之间似乎都没有使用该缓存,因此可以在writeObject()
调用之后直接调用reset()
.
You can reset that "cache" by calling reset()
on your ObjectOutputStream
. Since you don't seem to be making use of that cache between writeObject
calls anyway, you could call reset()
directly after the writeObject()
call.
这篇关于序列化期间堆空间不足的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!