如何处理"java.lang。Java堆空间错误;错误呢?

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

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

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

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

如果你能告诉我上述想法的细节,或者像自动虚拟内存,动态扩展堆大小这样的替代方案,那就太好了。

1958340 次浏览

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

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

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

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

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

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

# EYZ0。

是的,使用-Xmx,您可以为JVM配置更多内存。 确保你不会泄露或浪费内存。获取堆转储并使用Eclipse内存分析器来分析内存消耗。< / p >

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

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

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

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

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

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

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

我在其他地方读到过,你可以尝试- 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();

如果你继续分配&保持对对象的引用,您将填满您所拥有的任何数量的内存。

一个选择是做一个透明的文件关闭&当他们切换标签时打开(你只保留一个指向文件的指针,当用户切换标签时,你关闭&清理所有物品…它会使文件更改变慢…但是…),并且可能只在内存中保留3或4个文件。

您应该做的另一件事是,当用户打开一个文件时,加载它并拦截任何OutOfMemoryError,然后(因为不可能打开该文件)关闭该文件,清除其对象并警告用户他应该关闭未使用的文件。

您动态扩展虚拟内存的想法并不能解决这个问题,因为机器的资源是有限的,所以您应该小心&处理内存问题(或者至少要小心处理)。

我所看到的关于内存泄漏的一些提示是:

请记住,如果你把一个东西放入一个集合,然后忘记它,你仍然有一个强引用,所以取消集合,清理它或对它做些什么…如果没有,您将发现内存泄漏很难找到。

也许,使用弱引用的集合(weakhashmap…)可以帮助解决内存问题,但你要小心,因为你可能会发现你要找的对象已经被收集了。

我发现的另一个想法是开发一个持久的集合,存储在数据库对象最少使用和透明加载。这可能是最好的方法……

您可以指定项目需要多少堆空间

以下是Eclipse Helios /朱诺/开普勒:

鼠标右键单击

 Run As - Run Configuration - Arguments - Vm Arguments,

然后加上这个

-Xmx2048m

我也遇到了同样的问题,从java堆大小。

如果您使用java 5(1.5),我有两个解决方案。

  1. 只需安装jdk1.6,然后转到eclipse的首选项,并设置jav1 1.6的jre路径。

  2. 检查你的VM参数,不管它是什么。 只需在VM参数中所有参数的下面添加一行 -Xms512m -Xmx512m - xx: MaxPermSize =…m(192)。< / p > < /李>

我认为它会起作用……

VM参数在eclipse中为我工作。如果您使用的是eclipse 3.4版本,请执行以下操作

转到Run --> Run Configurations -->,然后在maven build—>下选择项目,然后选择选项卡“JRE”—>,然后输入-Xmx1024m

或者你可以输入Run --> Run Configurations --> select the "JRE" tab -->,然后输入-Xmx1024m

这将增加所有构建/项目的内存堆。以上内存大小为1gb。你可以按照你想要的方式进行优化。

在java中解决OutOfMemoryError的简单方法是通过使用JVM选项-Xmx512M来增加最大堆大小,这将立即解决您的OutOfMemoryError。这是我在Eclipse, Maven或ANT中得到OutOfMemoryError时的首选解决方案,因为基于项目的大小,您可以很容易地耗尽内存。

这是一个增加JVM最大堆大小的例子,如果你在java应用程序中设置堆大小,最好保持-Xmx与-Xms的1:1或1:1.5的比例。

# EYZ0

参考链接

遵循以下步骤:

  1. 从tomcat/bin打开catalina.sh

  2. 修改JAVA_OPTS为

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m
    -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
    
  3. Restart your tomcat

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

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

我想添加oracle 故障排除文章中的建议。

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

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

可能的原因:

  1. 简单配置问题,其中指定的堆大小不足以满足应用程序。

  2. 应用程序无意中持有对对象的引用,这将防止对象被垃圾收集。

  3. 终结词的过度使用

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

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

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

默认情况下,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 . # EYZ0

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

如果这个问题发生在Wildfly 8和JDK1.8中,那么我们需要指定MaxMetaSpace设置而不是PermGen设置。

例如,我们需要在wildfly的setenv.sh文件中添加以下配置。 # EYZ0 < / p >

更多信息请查看Wildfly堆问题

对于netbeans,您可以设置最大堆大小来解决这个问题。

转到“运行”,然后——>“设置项目配置”——>“自定义”——>“运行”其弹出窗口——>“虚拟机选项”——>填写“-Xms2048m -Xmx2048m”。

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

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

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

我的旧信息是: -Xmx128m - xx: MaxPermSize = 128 m < / p >

我所操作的新修改:

< p > -Xmx512m - xx: MaxPermSize = 512 m < / p >

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

谢谢

在android studio中添加/更改gradle.properties (Global Properties)结尾的这一行:

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

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

Android工作室

文件→无效缓存和重新启动解决了我:)

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

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

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

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

如果这个错误发生在junit测试执行之后,那么你应该执行构建 -># EYZ1。

android / gradle.properties中添加以下代码:

org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true

如果这个错误在APK生成过程中出现在react-native中,cd到你的项目中的android文件夹,并执行:

./gradlew clean

然后

./gradlew assembleRelease

如果错误仍然存在,那么重新启动计算机。

如果你来这里搜索这个问题从REACT NATIVE。

那我想你应该这么做

cd android/ && ./gradlew clean && cd ..

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

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

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

如果你使用的是Android Studio,只需添加这些行gradle.properties文件

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

在我的例子中,它通过在intellij设置中为Shared build process heap size分配更多内存来解决。

进入intellij settings >编译器比;共享构建过程堆大小

enter image description here

在Intellij中,我只需要给出“Build project”;

enter image description here