线程“main”中的异常java.lang.OutOfMemoryError:超出了GC开销限制

时间:2011-07-15 15:49:12

标签: java out-of-memory

我无法运行我的流程。它给出了以下异常:“线程中的异常”main“java.lang.OutOfMemoryError:Java堆空间”

  

java -Xms32m -Xmx516m FilteringSNP_genus   线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间           at java.util.Arrays.copyOf(Arrays.java:2882)           at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)           在java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:515)           在java.lang.StringBuffer.append(StringBuffer.java:306)           在java.io.BufferedReader.readLine(BufferedReader.java:345)           在java.io.BufferedReader.readLine(BufferedReader.java:362)           在FilteringSNP_genus.main(FilteringSNP_genus.java:65)

我尝试了不同的内存使用配置,如:

  

java -Xms32m -Xmx1024m FilteringSNP_genus

但它没有用,并且增加-XmxVALUE已经超出了GC开销限制:

  

线程“main”中的异常java.lang.OutOfMemoryError:超出了GC开销限制           at java.lang.String.substring(String.java:1940)           at java.util.StringTokenizer.nextToken(StringTokenizer.java:335)           在FilteringSNP_genus.main(FilteringSNP_genus.java:77)

有人能提供一些线索来解决这个问题吗?

由于

2 个答案:

答案 0 :(得分:7)

我猜测你正在从文件或套接字中读取并使用readLine()以方便使用而不考虑其含义。请改为reading into a char[] buffer

或者,你正在读取内存中的行并在内存中存储硬引用,所以一旦你阅读完了,你显然会用完房间。

对于GC开销错误,根据Oracle JVM article: “如果在垃圾收集中花费了太多时间,则并行收集器将抛出OutOfMemoryError:如果在垃圾收集中花费了超过98%的总时间并且恢复了不到2%的堆,则将抛出OutOfMemoryError。 “

答案 1 :(得分:1)

我发现GC会放弃,如果找到内存需要太长时间,即使内存确实存在。最简单的问题是当内存主要是虚拟内存时,它比实际内存慢得多。此外,如果内存过于分散,GC可能需要一些时间来找到所需的空间。如果你要分配大块内存,那可能会使情况更糟。像这样的问题可能是间歇性的,当GC有时间清理房屋并保持一切有条理并且在超载时失败时工作正常。我的猜测是,在你的情况下你要么有一个分页问题,​​要么你在太大的块中使用了太多的可用内存。

解决方案:获得更多真实内存(如果分页是问题)。使用更少的内存。使用较小的内存。数组是压缩数字的最快方法,但带有指针的数据结构使GC的生活更轻松。如果您可以想办法使用较小的数组(或没有数组),那就这样做。

应该有可能获得一个具有8GB或更多内存的正确64位系统(计算机和JVM),这样你就可以忽略并忘记这个问题,但我还没有听到有人这样做。 (并且内存使用扩展以填充可用的内存......)