如何处理“java.lang.OutOfMemoryError:java堆空间”错误?

我正在Java5上编写一个客户端Swing应用程序(图形字体设计器)。最近,我遇到了java.lang.OutOfMemoryError:java堆空间错误,因为我在内存使用方面并不保守。用户可以打开无限数量的文件,程序将打开的对象保存在内存中。经过快速研究,我发现5.0 Java虚拟机中的人体工程学和其他在Windows机器上说JVM默认最大堆大小为64MB

在这种情况下,我应该如何处理这种限制

我可以使用java的命令行选项增加最大堆大小,但这需要计算可用RAM并编写一些启动程序或脚本。此外,增加到某个finitemax并不能最终摆脱这个问题

我可以重写一些代码,以便经常将对象持久化到文件系统(使用数据库也是一样),从而释放内存。这可能行得通,但可能也要做很多工作

如果您能给我指出上述想法的细节,或者一些替代方案,如自动虚拟内存、动态扩展堆大小等,那就太好了

最终,无论在哪个平台上运行,您都可以使用有限的最大堆。在Windows 32位中,这大约是2GB(不是堆,而是每个进程的内存总量)。恰好Java选择将默认值变小(可能是为了让程序员无法创建内存分配失控的程序,而不遇到这个问题,并且必须准确地检查它们在做什么)

因此,有几种方法可以用来确定所需的内存量或减少正在使用的内存量。Java或C等垃圾收集语言的一个常见错误是保留对不再使用的对象的引用,或者在可以重用对象时分配许多对象。只要对象有对它们的引用,它们就会继续使用堆空间,因为垃圾收集器不会删除它们

在这种情况下,您可以使用Java内存分析器来确定程序中的哪些方法正在分配大量对象,然后确定是否有办法确保不再引用这些对象,或者一开始就不分配它们。我过去使用过的一个选项是“JMP”http://www.khelekore.org/jmp/

如果您确定分配这些对象是有原因的,并且需要保留引用(取决于您正在执行的操作,可能是这种情况),那么启动程序时只需要增加最大堆大小。但是,一旦您完成了内存分析并了解了对象是如何分配的,您就应该更好地了解您需要多少内存

一般来说,如果您不能保证您的程序将在有限的内存中运行(可能取决于输入大小),您将始终遇到这个问题。只有在耗尽所有这些之后,您才需要研究将对象缓存到磁盘等。此时,您应该有一个很好的理由说“我需要Xgb的内存”,而您不能通过改进算法或内存分配模式来解决它。通常情况下,这只适用于在大型数据集(如数据库或某些科学分析程序)上运行的算法,然后缓存和内存映射IO等技术变得有用

发表评论