我正在使用StringBuilder,读取文件的每个推文并在将其过滤到另一个文件后写入。我也在每个循环结束时刷新我的StringBuilder。我在2012年中期的8GB RAM视网膜上。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:535)
at java.lang.StringBuffer.append(StringBuffer.java:322)
at java.io.BufferedReader.readLine(BufferedReader.java:363)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at Parser.main(Parser.java:52)
答案 0 :(得分:1)
听起来你有内存泄漏。很难在没有源代码的情况下为您提供具体的代码建议,但是即使在刷新后,您可能还有一些对StringBuilder的引用? VisualVM是一个很好的免费工具,可用于跟踪运行时此类问题的发生位置。此博客文章介绍了如何执行此操作:http://rejeev.blogspot.com/2009/04/analyzing-memory-leak-in-java.html
答案 1 :(得分:0)
从程序的结构中,我们可以得出结论,内存耗尽是在循环的每次迭代中变大的对象(情况1),或者是在单次迭代中变大的对象(情况2)。
当BufferedReader尝试调整其内部字符缓冲区的大小以容纳一行输入时,堆栈跟踪表示内存分配失败。失败时这条线有多长?您可以在调试器中运行程序,在OutOfMemoryError上使用异常断点,并检查保存无法分配的数组大小的变量。如果它不是很大,我们可以排除案例2.
案例1最可能的嫌疑人是LinkedHashSet,它存储输出中所有推文的tweet_f。尝试估计其大小(可以使用ln.size()*(50 + 2 *字符串中的字符串长度)获得粗略估计值,并确保您有足够的内存来保存它。
如果失败了,我会拿出繁重的工具,即进行堆转储,将其加载到VisualVM或商业分析器等分析工具中,请求该工具识别大对象以及哪些引用这些对象阻止了它们的垃圾收集。