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

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

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

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

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


当前回答

默认情况下,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内部数据结构。

其他回答

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

详情请看这里。

我想添加建议从甲骨文故障排除文章。

线程thread_name异常:Java .lang. outofmemoryerror: Java堆空间

详细消息Java堆空间表示无法在Java堆中分配对象。此错误并不一定意味着内存泄漏

可能的原因:

简单的配置问题,指定的堆大小不足以满足应用程序的要求。 应用程序无意中持有对对象的引用,这可以防止对象被垃圾收集。 过度使用终结符。

此错误的另一个潜在来源来自于过度使用终结器的应用程序。如果类具有finalize方法,则该类型的对象在垃圾收集时不会回收其空间

在垃圾收集之后,对象将排队等待终结,这将在稍后发生。终结器由服务终结队列的守护线程执行。如果终结器线程无法跟上终结队列,那么Java堆就会被填满,并抛出这种类型的OutOfMemoryError异常。

可能导致这种情况的一种场景是,应用程序创建了高优先级线程,导致终结队列的增长速度快于终结线程服务该队列的速度。

注意,如果您在部署情况下需要这样做,请考虑使用Java WebStart(使用“ondisk”版本,而不是网络版本——可能在Java 6u10或更高版本中),因为它允许您以跨平台的方式向JVM指定各种参数。

否则,你将需要一个特定于操作系统的启动器来设置你需要的参数。

在android studio中添加/更改gradle末尾的这一行。属性(全局属性):

...
org.gradle.jvmargs=-XX\:MaxHeapSize\=1024m -Xmx1024m 

如果它不起作用,您可以重试大于1024的堆大小。

当数据库连接池满时,Java OOM堆空间问题也会出现。

我遇到这个问题是因为我的Hikari连接池(升级到Spring boot 2.4.*时)已满,无法再提供连接(所有活动连接仍在等待从数据库获取结果)。

问题是我们在JPA存储库中的一些本地查询包含ORDER BY ?#{#pageable},这需要很长时间才能获得升级时的结果。

从JPA存储库中的所有本机查询和OOM堆空间问题以及连接池问题中删除ORDER BY ?#{#pageable}。