jvm—如何处理“java.lang.outofmemoryerror:java堆空间”错误?

wvyml7n5  于 2021-06-27  发布在  Hive
关注(0)|答案(14)|浏览(564)

我正在Java5上编写一个客户端swing应用程序(图形字体设计器)。最近,我遇到了 java.lang.OutOfMemoryError: Java heap space 错误,因为我不是保守的内存使用。用户可以打开无限数量的文件,程序将打开的对象保存在内存中。经过一番快速的研究,我发现5.0java虚拟机符合人体工程学,其他人认为在windows机器上jvm默认最大堆大小为 64MB .
在这种情况下,我应该如何处理这个约束?
我可以使用java的命令行选项来增加最大堆大小,但这需要找出可用的ram并编写一些启动程序或脚本。此外,增加到某个有限的最大值并不能最终消除这个问题。
我可以经常重写一些代码,将对象持久化到文件系统(使用数据库也是一样),以释放内存。它可以工作,但它可能是一个很大的工作。
如果您能给我指出上述想法的细节,或者自动虚拟内存、动态扩展堆大小之类的替代方案,那就太好了。

nwwlzxa7

nwwlzxa71#

大警告——在我的办公室,我们发现(在一些windows机器上)我们不能为java堆分配超过512m的内存。这原来是由于卡巴斯基反病毒产品安装在其中一些机器上。卸载av产品后,我们发现至少可以分配1.6gb,即, -Xmx1600m (m是强制的,否则会导致另一个错误“初始堆太小”)工作。
不知道这种情况是否发生在其他av产品上,但可能是因为av程序在每个地址空间中都保留了一小块内存,从而防止了一次非常大的分配。

atmip9wb

atmip9wb2#

我在java堆大小方面也遇到了同样的问题。
如果您使用的是Java5(1.5),我有两个解决方案。
只需安装jdk1.6并转到eclipse的preferences,设置jav1.6的jre路径。
检查你的vm参数,不管它是什么。只需在vm参数中存在的所有参数下面添加一行-xms512m-xmx512m-xx:maxpermsize=…m(192m)。
我想会有用的。。。

7y4bm7vi

7y4bm7vi3#

我想补充一下oracle故障排除文章中的建议。
线程名称中出现异常:java.lang.outofmemoryerror:java堆空间
详细消息java heap space指示无法在java堆中分配对象。此错误不一定意味着内存泄漏
可能原因:
简单的配置问题,指定的堆大小不足以满足应用程序的需要。
应用程序无意中持有对对象的引用,这防止了对象被垃圾收集。
过度使用终结器。
此错误的另一个潜在来源是过度使用终结器的应用程序。如果类具有finalize方法,则该类型的对象在垃圾收集时不会回收其空间
垃圾回收之后,对象将排队等待终结,这将在稍后发生。终结器由为终结队列提供服务的守护进程线程执行。如果终结器线程无法跟上终结队列,那么java堆可能会被填满,并且会抛出这种类型的outofmemoryerror异常。
可能导致这种情况的一种情况是,当应用程序创建高优先级线程时,这些线程会导致终结队列以比终结器线程为该队列提供服务的速度更快的速度增加。

8nuwlpux

8nuwlpux4#

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

xqk2d5yq5#

增加堆大小不是一个“修复”,而是一个“石膏”,100%临时的。它会在其他地方再次崩溃。要避免这些问题,请编写高性能代码。
尽可能使用局部变量。
确保选择了正确的对象(例如:string、stringbuffer和stringbuilder之间的选择)
为你的程序使用一个好的代码系统(例如:使用静态变量和非静态变量)
其他可以对你的代码起作用的东西。
试着多线程移动

dpiehjr4

dpiehjr46#

如果需要在运行时监视内存使用情况,则 java.lang.management 套餐优惠 MBeans 它可以用来监视vm中的内存池(例如eden空间、终身生成等),还可以监视垃圾收集行为。
这些MBean报告的可用堆空间将因gc行为而大不相同,特别是当您的应用程序生成大量稍后gc-ed的对象时

xjreopfe

xjreopfe7#

是的,有 -Xmx 您可以为jvm配置更多内存。以确保不会泄漏或浪费内存。进行堆转储并使用eclipse内存分析器分析内存消耗。

von4xj4u

von4xj4u8#

使用命令行选项运行java -Xmx ,设置堆的最大大小。
详见此处。

v1l68za4

v1l68za49#

最终,无论您在哪个平台上运行,您总是可以使用有限的最大堆。在windows 32位中,这是 2GB (不是堆,而是每个进程的内存总量)。恰好java选择将缺省值变小(大概是为了让程序员不能创建内存分配失控的程序,而不遇到这个问题,并且必须检查它们正在做什么)。
因此,有几种方法可以用来确定需要多少内存,或者减少正在使用的内存。垃圾收集语言(如java或c)的一个常见错误是保留对不再使用的对象的引用,或者在可以重用对象时分配许多对象。只要对象有对它们的引用,它们就会继续使用堆空间,因为垃圾收集器不会删除它们。
在这种情况下,您可以使用java内存探查器来确定程序中的哪些方法正在分配大量对象,然后确定是否有方法确保这些对象不再被引用,或者一开始就不分配它们。我过去使用的一个选项是“jmp”http://www.khelekore.org/jmp/.
如果您确定分配这些对象是有原因的,并且需要保留引用(取决于您正在执行的操作,可能是这种情况),那么您只需要在启动程序时增加最大堆大小。但是,一旦您完成了内存分析并了解了对象是如何分配的,您就应该更好地了解您需要多少内存。
一般来说,如果您不能保证您的程序将在有限的内存中运行(可能取决于输入大小),您将总是遇到这个问题。只有在用尽所有这些之后,您才需要研究将对象缓存到磁盘等。在这一点上,您应该有一个很好的理由对某些东西说“我需要xgb的内存”,而您不能通过改进算法或内存分配模式来解决它。通常情况下,这只适用于在大型数据集(如数据库或一些科学分析程序)上运行的算法,然后缓存和内存Mapio等技术变得有用。

7eumitmz

7eumitmz10#

您可以指定每个项目需要多少堆空间
以下是eclipse helios/juno/kepler的:
用鼠标右键单击

Run As - Run Configuration - Arguments - Vm Arguments,

再加上这个

-Xmx2048m
bbmckpt7

bbmckpt711#

vm参数在eclipse中对我有效。如果您使用的是eclipse3.4版,请执行以下操作
Run --> Run Configurations --> 然后选择maven build-->下的项目,然后选择选项卡“jre”-->然后输入 -Xmx1024m .
或者你也可以 Run --> Run Configurations --> select the "JRE" tab --> 然后输入- Xmx1024m 这将增加所有构建/项目的内存堆。以上内存大小为1 gb。你可以优化你想要的方式。

nnt7mjpx

nnt7mjpx12#

简单的解决方法 OutOfMemoryError 在java中,通过使用jvm选项来增加最大堆大小 -Xmx512M ,这将立即解决outofmemoryerror。当我在构建项目时遇到eclipse、maven或ant中的内存错误时,这是我首选的解决方案,因为根据项目的大小,很容易耗尽内存。
下面是一个增加jvm最大堆大小的示例,如果您在java应用程序中设置堆大小,那么最好保持-xmx到-xms的比率为1:1或1:1.5。 export JVM_ARGS="-Xms1024m -Xmx1024m" 参考链接

lp0sw83n

lp0sw83n13#

默认情况下,对于开发,jvm对其他与性能相关的特性使用小尺寸和小配置。但是对于生产,您可以进行调优,例如(此外,还可以存在特定于it应用程序服务器的配置)->(如果仍然没有足够的内存来满足请求,并且堆已经达到最大大小,则会发生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"
  1. service tomcat restart 注意,jvm使用的内存不仅仅是堆。例如,java方法、线程堆栈和本机句柄在内存中与堆以及jvm内部数据结构分开分配。
fafcakar

fafcakar14#

遵循以下步骤:
打开 catalina.sh 来自tomcat/bin。
将java\u选项更改为

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

相关问题