我正在为一个大文件(~30GB)实现外部排序,所以在我在磁盘中写入块后,我创建chunks
次BufferedReader(new OutputStreamWriter(new FileOutputStream(outputPath), "UTF-8"), maxBufferSize)
为maxBufferSize = Runtime.getRuntime().freeMemory() / chunks
。但是我得到OutOfMemory
例外。
我猜垃圾收集器没有足够的时间来清理内存(当我停止使用调试器时它不会抛出异常),但在这种情况下,为什么会给Runtime.getRuntime().freeMemory()
结果?
是否可以显式调用垃圾收集,或者唯一的选择是将进程暂停一段时间?
答案 0 :(得分:2)
是否可以显式调用垃圾收集
是的,这是可能的。但它没有任何好处。
JVM只会在执行完整GC后抛出OOME。明确地调用System.gc()
(很可能)只会浪费CPU时间。
实际上,我认为你真正的问题在于:
我创建
chunks
次BufferedReader(new OutputStreamWriter(new FileOutputStream(outputPath), "UTF-8"), maxBufferSize)
为maxBufferSize = Runtime.getRuntime().freeMemory() / chunks
。
当您考虑各种对象开销时,(maxBufferSize + overheads) * chunks
可能比可用内存量大一点。
通常,使用接近完整的Java堆运行是个坏主意。即使你没有完全耗尽空间,你也会发现接近完全运行将触发许多(太多)垃圾收集。
在这种情况下,你真的从拥有非常大的I / O缓冲区中获益很多。 8KB到64KB范围内的缓冲区应该没问题......这是我的直觉。另见Peter Lawrey的评论!
答案 1 :(得分:0)
您可以尝试使用System.gc()
,但它不是最有用的。您可以尝试为程序提供更多内存。