如何处理“java.lang.OutOfMemoryError:Java堆空间”错误(64MB堆大小)

问题

我正在写一个客户端Swing应用程序(图形字体设计器)onJava 5.最近,我遇到了java.lang.OutOfMemoryError: Java heap space错误,因为我对内存使用情况并不保守。用户可以打开无限数量的文件,程序将打开的对象保存在内存中。经过快速研究后,我发现Ergonomics in the 5.0 Java Virtual Machine和其他人在Windows机器上说JVM默认最大堆大小为64MB

鉴于这种情况,我该如何处理这种约束?

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

我可以重写我的一些代码来经常将对象持久化到文件系统(使用数据库是一回事)来释放内存。它可以工作,但它也可能很多工作。

如果你可以向我指出上述想法或某些替代方案的详细信息,例如自动虚拟内存,动态扩展堆大小,这将是很好的。


#1 热门回答(191 赞)

无论你运行的是什么平台,最终都可以使用有限的最大堆。在Windows 32位中,这大约是2gb(不是专门的堆,而是每个进程的总内存量)。只是碰巧Java选择使默认值更小(可能是因为程序员无法创建具有失控内存分配的程序而不会遇到此问题并且必须仔细检查他们正在做什么)。

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

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

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

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


#2 热门回答(98 赞)

使用命令行选项-Xmx运行Java,该选项设置堆的最大大小。

See here for details.


#3 热门回答(74 赞)

你可以为每个项目指定项目所需的堆空间

以下是针对873751614 Eclipse Helios / Juno / Kepler**:

单击鼠标右键

Run As - Run Configuration - Arguments - Vm Arguments,

然后加上这个

-Xmx2048m