如何在Java中处理OutOfMemoryError?
我必须序列化大约一百万个项目,当我运行代码时,会出现以下异常:如何在Java中处理OutOfMemoryError?,java,memory-management,Java,Memory Management,我必须序列化大约一百万个项目,当我运行代码时,会出现以下异常: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRange(Unknown Source) at java.lang.String.<init>(Unknown Source) at java.io.BufferedReader.readLine(Unk
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at org.girs.TopicParser.dump(TopicParser.java:23)
at org.girs.TopicParser.main(TopicParser.java:59)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间
位于java.util.Arrays.copyOfRange(未知源)
位于java.lang.String。(未知源)
位于java.io.BufferedReader.readLine(未知源)
位于java.io.BufferedReader.readLine(未知源)
位于org.girs.TopicParser.dump(TopicParser.java:23)
位于org.girs.TopicParser.main(TopicParser.java:59)
我该怎么处理 使用选项-Xmx的较大值启动java,例如-Xmx512m理想情况下,重新构造代码以使用较少的内存。例如,您可以将输出流化,而不是将整个内容保存在内存中
或者,只需使用
-Xmx
选项为JVM提供更多内存。您不应该在代码中处理它。OutOfMemory不应被捕获和处理。相反,用更大的堆空间启动JVM
java -Xmx512M
我们应该做到这一点
有关更多详细信息,请参见。您可以使用-Xmx选项增加java使用的内存大小,例如:
java -Xmx512M -jar myapp.jar
更好的方法是减少应用程序的内存占用。你序列化了数百万项?你需要把它们都保存在内存中吗?或者你能在使用它们之后释放一些吗?尽量减少使用的对象。您会遇到OutOfMemory错误,因为您的程序需要的内存比JVM可用的内存多。在运行时,您无法专门做任何事情来帮助实现这一点 正如krosenvold所指出的,您的应用程序可能对内存提出了合理的要求,但恰好JVM启动时内存不足(例如,您的应用程序将有280MB的峰值内存占用,但JVM启动时只有256MB)。在这种情况下,增加分配的大小将解决此问题 如果您觉得在启动时提供了足够的内存,那么您的应用程序可能暂时使用了太多内存,或者内存泄漏。在您发布的情况下,听起来好像您同时持有对内存中所有百万项的引用,即使您可能正在按顺序处理它们 检查“完成”的项目的引用是什么样的-你应该尽快遵从这些,以便它们可以被垃圾收集。例如,如果要向一个集合添加一百万个项,然后在该集合上迭代,则需要足够的内存来存储所有这些对象实例。看看是否可以一次获取一个对象,序列化它,然后放弃引用
如果您在解决此问题时遇到困难,发布一个伪代码片段会有所帮助。使用transient关键字标记可从现有数据生成的序列化类中的字段。
实现writeObject和readObject,以帮助重建瞬态数据。除了提供给您的一些提示之外,还可以查看内存不足和 还可以使用更多内存(-Xmx512M)启动JVM。 看起来您有OutOfMemoryError,因为您的TopicParser读取的行可能非常大(这是您应该避免的),您可以使用FileReader(或者,如果编码有问题,可以使用包装FileInputStream的InputStreamReader)。将其read(char[])方法与大小合理的char[]数组一起用作缓冲区 最后还要调查一下为什么可以使用OutOfMemoryError -XX:+HEAPDUMPONAUTOFMEMORYERROR JVM中的标志,以将转储堆信息获取到磁盘
祝你好运 没有真正的好办法处理它。一旦发生,你就处于未知的领域。您可以通过名称-OutOfMemoryError来判断。它被描述为: 当 Java虚拟机无法分配对象,因为该对象已过期 内存,垃圾箱无法提供更多内存 收集器 通常OutOfMemoryError表示系统/方法存在严重错误(很难指出触发它的特定操作) 通常情况下,这与heapspace的正常运行有关。使用-verbosegc和前面提到的-XX:+HeapDumpOnOutOfMemoryError应该会有所帮助
你可以在上找到这个问题的简明摘要。我知道Java的官方答案是“哦,不!内存不足!我屈服了!”。对于那些在内存不足不允许成为致命错误(例如,编写操作系统或为不受保护的操作系统编写应用程序)的环境中编程的人来说,这都是相当令人沮丧的 放弃的意愿是必要的——您不能控制Java内存分配的每个方面,因此您不能保证您的程序在内存不足的情况下成功。但这并不意味着你必须不战而下 不过,在战斗之前,你可以想办法避免这种需要。也许您可以避免Java序列化,而是定义自己的数据格式,而不需要大量内存分配来创建。序列化分配了大量内存,因为它保留了以前看到的对象的记录,因此如果对象再次出现,它可以按编号引用它们,而不是再次输出它们(这可能导致无限循环)。但这是因为它需要通用性:根据您的数据结构,您可能能够定义一些文本/二进制/XML/任何表示形式,这些表示形式只需写入流,而不需要存储额外的状态。或者,您可以安排您需要的任何额外状态始终存储在对象中,而不是在序列化时创建 如果您的应用程序执行的某个操作占用大量内存,但大多数情况下占用的内存要少得多,特别是如果该操作是由用户启动的,并且如果您找不到使用更少内存或使更多内存可用的方法,那么它可能是值得的
catch (Throwable ex){
if (!(ex instanceof ThreadDeath))
{
ex.printStackTrace(System.err);
}}