如何处理“java.lang.OutOfMemoryError:Java堆空间”错误(64MB堆大小)
我正在Java 5上编写客户端Swing应用程序(graphics字体devise器)。 最近,我正在运行java.lang.OutOfMemoryError: Java heap space
错误,因为我不是保守的内存使用情况。 用户可以打开无限数量的文件,程序将打开的对象保存在内存中。 经过一个快速的研究,我发现5.0 Java虚拟机中的人机工程学和其他人在Windows机器上的JVM默认最大堆大小为64MB
。
鉴于这种情况,我该如何处理这个约束呢?
我可以使用java的命令行选项来增加最大堆大小 ,但是这需要找出可用的RAM并编写一些启动程序或脚本。 此外,增加一些有限的最大值不会最终摆脱这个问题。
我可以重写一些我的代码来经常保存对象到文件系统(使用数据库是一样的)来释放内存。 它可以工作,但也可能是很多工作。
如果你能指出我的细节以上的想法或像自动虚拟内存一样的select,dynamic扩展堆大小 ,这将是伟大的。
最终,无论您在哪个平台上运行,您总是可以使用有限的最大堆。 在Windows 32位,这是大约2GB(不是特别堆,但每个进程的总内存量)。 恰巧Javaselect使默认值更小(大概是这样,程序员不能创build那些没有遇到这个问题而不得不仔细检查内存分配的程序)。
所以这里给出了几种方法来确定你需要的内存量或者减less你使用的内存量。 使用垃圾收集语言(如Java或C#)的一个常见错误是,不要使用对象的引用,或者在可以重用对象时分配多个对象。 只要对象具有对它们的引用,它们将继续使用堆空间,因为垃圾收集器不会删除它们。
在这种情况下,您可以使用Java内存分析器来确定程序中的哪些方法正在分配大量对象,然后确定是否有方法确保不再引用它们,或者不首先分配它们。 我曾经使用过的一个选项是“JMP” http://www.khelekore.org/jmp/ 。
如果您确定要分配这些对象是有原因的,并且需要保留引用(取决于您正在做什么,可能会出现这种情况),则只需在启动程序时增加最大堆大小即可。 然而,一旦你做了内存分析,并了解你的对象如何分配,你应该有一个更好的想法,你需要多less内存。
一般来说,如果你不能保证你的程序运行在一些有限的内存(也许取决于input大小),你将会遇到这个问题。 只有在耗尽了所有这些之后,你才需要将caching对象存入磁盘等。在这一点上,你应该有一个非常好的理由来说“我需要Xgb的内存”,你不能通过改进来解决它你的algorithm或内存分配模式。 通常情况下,对于在大型数据集(如数据库或某些科学分析程序)上运行的algorithm,通常情况就是这样,然后像caching和内存映射IO这样的技术就变得有用了。
使用命令行选项-Xmx
运行Java,该选项设置堆的最大大小。
详情请看这里。 。
你可以指定每个项目你的项目需要多less堆空间
以下是Eclipse Helios / Juno / Kepler :
点击鼠标右键
Run As - Run Configuration - Arguments - Vm Arguments,
然后添加这个
-Xmx2048m
大警告—-在我的办公室,我们发现(在某些Windows机器上)我们无法为Java堆分配超过512m的空间。 原来,这是由于某些机器上安装了卡巴斯基反病毒产品。 卸载该AV产品后,我们发现我们可以分配至less1.6GB,即-Xmx1600m(m是强制性的,否则会导致另一个错误“初始堆太小”)工作。
不知道这是否与其他AV产品发生,但大概是这样,因为AV程序在每个地址空间保留一小块内存,从而防止一个真正的大分配。
增加堆的大小不是一个“修复”,它是一个“石膏”,100%是暂时的。 它会在别的地方再次崩溃。 为了避免这些问题,编写高性能的代码。
- 尽可能使用局部variables。
- 确保你select了正确的对象(EX:String,StringBuffer和StringBuilder之间的select)
- 为你的程序使用一个好的代码系统(EX:使用静态variablesVS非静态variables)
- 其他的东西可以在你的代码上工作。
- 尝试移动multy螺纹
VM的论点在日食中为我工作。 如果您使用的是Eclipse 3.4版,请执行以下操作
去Run --> Run Configurations -->
然后selectmaven build下的项目 – >然后select选项卡“JRE” – >然后input-Xmx1024m
。
或者你可以做Run --> Run Configurations --> select the "JRE" tab -->
然后input – Xmx1024m
这应该增加所有构build/项目的内存堆。 以上内存大小是1 GB。 你可以优化你想要的方式。
是的,使用-Xmx,您可以为您的JVMconfiguration更多的内存。 确保你不会泄漏或浪费内存。 采取堆转储并使用Eclipse内存分析器来分析您的内存消耗。
我想添加来自oracle 疑难解答文章的build议
线程中的exceptionthread_name: java.lang.OutOfMemoryError:Java堆空间
详细信息Java堆空间表示对象不能在Java堆中分配。 这个错误并不一定意味着内存泄漏
可能的原因:
-
简单的configuration问题 ,指定的堆大小不足以应用程序。
-
应用程序无意中持有对对象的引用 ,这可以防止对象被垃圾收集。
-
终结者过度使用 。
此错误的另一个潜在来源是过度使用终结器的应用程序。 如果一个类有一个finalize方法,那么这个types的对象在垃圾回收时没有回收空间
在垃圾收集之后 ,对象排队等待终止 ,这在稍后发生。 终结器由服务于终结队列的守护线程执行。 如果终结器线程无法跟上终止队列,那么Java堆可能会被填满,这种types的OutOfMemoryErrorexception将被抛出。
一种可能导致这种情况的情况是应用程序创build高优先级的线程 ,导致终结队列以比终结线程服务该队列的速率更快的速率增加。
如果需要在运行时监视内存使用情况,java.lang.management包提供了可用于监视VM中内存池的MBean(例如,eden空间,tenured generation等)以及垃圾收集行为。
由这些MBean报告的可用堆空间将根据GC的行为而有很大差别,特别是如果您的应用程序生成大量的对象,那么以后进行GC编辑。 一种可能的方法是在每个完整的GC之后监视空闲的堆空间,您可以使用这个空间来决定是否通过持久对象释放内存。
最终,你最好的select是尽可能限制你的记忆力,同时性能仍然可以接受。 正如之前的评论指出的,内存总是有限的,但是你的应用程序应该有一个处理内存耗尽的策略。
我遇到了java堆大小相同的问题。 如果您使用java 5(1.5),我有两个解决scheme。
第一:只要安装jdk1.6并转到eclipse的首选项,并设置jav1 1.6的jrepath。
第二: – 检查你的虚拟机参数,让它成为无论如何。 只需在VM参数中存在的所有参数的下面添加一行为-Xms512m -Xmx512m -XX:MaxPermSize = … m(192m)。
我认为这将工作…
按以下步骤操作:
-
从tomcat / bin打开catalina.sh。
-
Chnage 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"
-
重新启动你的tomcat
请注意,如果您在部署情况下需要这样做,请考虑使用Java WebStart(使用“ondisk”版本,而不是networking版本 – 在Java 6u10及更高版本中可能),因为它允许您指定跨JVM的各种参数平台的方式。
否则,你将需要一个操作系统特定的启动器,它设置你需要的参数。
我读了其他地方,你可以尝试 – 赶上java.lang.OutOfMemoryError,并在catch块,你可以释放所有你知道可能会使用大量的内存,closures连接等资源,然后做一个System.gc()然后重新尝试你想要做的事情。
另一种方法是,虽然,我不知道这是否会工作,但我目前正在testing它是否会在我的应用程序上工作。
想法是通过调用已知的增加空闲内存的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();
在java中解决OutOfMemoryError
简单方法是通过使用JVM选项-Xmx512M
来增加最大堆大小,这将立即解决您的OutOfMemoryError。 这是我首选的解决scheme,当我在Eclipse,Maven或ANT中build立项目时因为OutOfMemoryError,因为基于项目的大小,你可以很容易地耗尽内存。
这里是增加JVM的最大堆大小的一个例子,如果你在你的Java应用程序中设置堆的大小,那么最好把-Xmx保持为-Xms比率为1:1或1:1.5。
export JVM_ARGS="-Xms1024m -Xmx1024m"
参考链接
如果你继续分配和保持对象的引用,你将填满你所拥有的任何内存。
一种select是在切换标签时closures并打开透明文件(只保留一个指向文件的指针,当用户切换标签页时,closures并清理所有对象…这会使文件变慢…但是…),也许只保留3或4个文件的内存。
你应该做的其他事情是,当用户打开一个文件,加载它,并拦截任何OutOfMemoryError,然后(因为它是无法打开文件)closures该文件,清理它的对象,并警告用户,他应该closures未使用文件。
您的dynamic扩展虚拟内存的想法并不能解决问题,因为机器资源有限,所以您应该小心并处理内存问题(至less要小心)。
我已经看到内存泄漏的几个提示是:
– >请记住,如果你把东西放入一个集合,然后忘了它,你仍然有一个强有力的参考,所以无效集合,清理它或做一些事情…如果不是,你会发现内存泄漏很难find。
– >也许,使用具有弱引用的集合(weakhashmap …)可以帮助解决内存问题,但是您必须小心,因为您可能会发现所查找的对象已被收集。
– >我发现的另一个想法是开发一个持久的集合,存储在最less使用和透明加载的数据库对象上。 这可能是最好的办法…
对于netbeans,您可以设置最大堆大小来解决问题。 首先进入'运行',然后 – >'设置项目configuration' – >'自定义' – >'运行'popup窗口 – >'虚拟机选项' – >填写'-Xms2048m – Xmx2048m”。
如果在Wildfly 8和JDK1.8中发生这个问题,那么我们需要指定MaxMetaSpace设置而不是PermGen设置。
比如我们需要在wildfly的setenv.sh文件中添加下面的configuration。 JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"
有关更多信息,请检查Wild堆问题
例如:在Linux平台上进行生产模式的优选设置。
用这种方式下载和configuration服务器之后http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/
1.在文件夹/ opt / tomcat / bin /下创buildsetenv.sh文件,
touch /opt/tomcat/bin/setenv.sh
打开并写入这个参数来设置更好的模式。
nano /opt/tomcat/bin/setenv.sh export CATALINA_OPTS="$CATALINA_OPTS -Xms512m" export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m" export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxPermSize=256m"
3. service tomcat restart