我正在使用 mstor 库来解析 mbox 邮件文件。一些文件的大小超过了千兆字节。可以想象,这可能会导致一些堆空间问题。
有一个循环,对于每次迭代,都会检索特定的消息。该getMessage()
调用是在用完时尝试分配堆空间的方法。如果我在这个循环的顶部添加一个调用System.gc()
,程序会毫无错误地解析大文件,但我意识到收集垃圾 40,000 次必须减慢程序的速度。
我的第一次尝试是让调用看起来像if (i % 500 == 0) System.gc()
每 500 条记录发生一次调用。我尝试提高和降低此数字,但结果不一致,通常会返回 OutOfMemory 错误。
我的第二个更聪明的尝试如下所示:
try {
message = inbox.getMessage(i);
} catch (OutOfMemoryError e) {
if (firstTry) {
i--;
firstTry = false;
} else {
firstTry = true;
System.out.println("Message " + i + " skipped.");
}
System.gc();
continue;
}
这个想法是只在抛出 OutOfMemory 错误时调用垃圾收集器,然后减少计数以重试。不幸的是,在解析了数千封电子邮件后,程序才开始输出:
Message 7030 skipped.
Message 7031 skipped.
....
以此类推。
我只是对每次迭代的收集器如何返回与此不同的结果感到困惑。据我了解,垃圾就是垃圾,所有这一切都应该改变的是在给定时间收集了多少。
谁能解释这种奇怪的行为?有没有人推荐其他方式来减少呼叫收集器的频率?我的堆空间已用完。