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

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

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

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

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


当前回答

我在其他地方读到过,你可以尝试- catch java.lang.OutOfMemoryError,在catch块上,你可以释放所有你知道可能使用大量内存的资源,关闭连接等等,然后执行System.gc(),然后重新尝试你要做的任何事情。

另一种方式是,虽然,我不知道这是否会工作,但我目前正在测试它是否会在我的应用程序上工作。

这个想法是通过调用System.gc()来进行垃圾收集,这可以增加可用内存。您可以在内存消耗代码执行之后继续检查。

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

其他回答

大警告----在我的办公室,我们发现(在一些windows机器上)我们不能为Java堆分配超过512m。事实证明,这是由于其中一些机器上安装了卡巴斯基反病毒产品。在卸载该AV产品后,我们发现我们可以分配至少1.6gb,即-Xmx1600m (m是强制性的,否则它将导致另一个错误“太小的初始堆”)工作。

不知道这种情况是否发生在其他反病毒产品上,但据推测,这是因为反病毒程序在每个地址空间中保留了一小块内存,从而防止了单个真正大的分配。

默认情况下,JVM对其他性能相关特性使用小尺寸和小配置。但是对于生产环境,您可以调优例如:>(如果仍然没有足够的内存来满足请求,并且堆已经达到了最大大小,则会发生OutOfMemoryError错误)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

例如:在linux平台上为生产模式首选设置。

下载并配置服务器后,以这种方式http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1.在/opt/tomcat/bin/目录下创建setenv.sh文件

   touch /opt/tomcat/bin/setenv.sh

2.打开并写入此参数以设置优选模式。

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

3.服务tomcat重启

请注意,JVM使用的内存不仅仅是堆。例如 Java方法、线程栈和本机句柄分配在内存中 与堆分离,以及JVM内部数据结构。

如果你需要在运行时监控你的内存使用情况,java.lang.management包提供了mbean,可以用来监控你的虚拟机中的内存池(例如伊甸园空间,终身生成等),以及垃圾收集行为。

根据GC行为的不同,这些mbean报告的空闲堆空间会有很大的变化,特别是如果您的应用程序生成了许多后来被GC-ed的对象。一种可能的方法是监视每次全gc之后的空闲堆空间,您可以使用它来决定是否通过持久化对象来释放内存。

最终,最好的办法是在性能可以接受的情况下尽可能限制内存保留。正如前面的评论所指出的,内存总是有限的,但你的应用程序应该有一个策略来处理内存耗尽。

遵循以下步骤:

从tomcat/bin打开catalina.sh。 将JAVA_OPTS更改为 JAVA_OPTS = " -Djava.awt。无头= true -Dfile。encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256 6m -XX:MaxNewSize=256 6m -XX:PermSize=256 6m - xx: MaxPermSize = 256 - xx: + DisableExplicitGC” 重新启动tomcat

如果在启动eclipse birt时出现此错误 1-你将进入eclipse配置文件 2-你必须打开eclipse.init 3-修改RAM内存,你可以增加这个,我给一个例子。

我以前的资料是: -Xmx128m - xx: MaxPermSize = 128

我所操作的新修改:

-Xmx512m - xx: MaxPermSize = 512

这一修改将允许我在浏览器中启动报告时解析Java堆空间。

谢谢