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

在这种情况下,我应该如何处理这个约束呢?

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

我可以重写一些代码,频繁地将对象持久化到文件系统中(使用数据库也是一样),以释放内存。它可能会起作用,但可能也要做很多工作。

如果你能告诉我上述想法的细节或一些替代方案,如自动虚拟内存,动态扩展堆大小,那将是伟大的。


当前回答

如果其他方法都失败了,除了增加最大堆大小外,还要尝试增加交换大小。对于Linux,到目前为止,相关说明可以在https://linuxize.com/post/create-a-linux-swap-file/中找到。

如果你在嵌入式平台上编译一些大的东西,这会很有帮助。

其他回答

增加堆大小不是一个“修复”,它是一个“膏药”,100%临时。它会在其他地方再次崩溃。要避免这些问题,请编写高性能代码。

尽可能使用局部变量。 确保你选择了正确的对象(EX:选择String, StringBuffer和StringBuilder之间) 为你的程序使用一个好的代码系统(例如:使用静态变量VS使用非静态变量) 其他可以在你的代码中工作的东西。 尝试用多线程移动

如果其他方法都失败了,除了增加最大堆大小外,还要尝试增加交换大小。对于Linux,到目前为止,相关说明可以在https://linuxize.com/post/create-a-linux-swap-file/中找到。

如果你在嵌入式平台上编译一些大的东西,这会很有帮助。

最终,无论您在哪个平台上运行,您总是有一个有限的堆的最大值可以使用。在Windows 32位中,这大约是2GB(不是具体的堆,而是每个进程的总内存)。只是碰巧Java选择将默认值设得更小(大概是为了让程序员创建的程序在内存分配失控的情况下不会遇到这个问题,并且必须检查它们正在做什么)。

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

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

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

In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.

将这条线添加到gradle中。属性文件

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

它应该会起作用。您可以相应地更改MaxPermSize来修复堆问题

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

详情请看这里。