如何处理“java.lang.OutOfMemoryError: Java heap space”错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to deal with "java.lang.OutOfMemoryError: Java heap space" error?
提问by Eugene Yokota
I am writing a client-side Swingapplication (graphical font designer) on Java 5. Recently, I am running into java.lang.OutOfMemoryError: Java heap space
error because I am not being conservative on memory usage. The user can open unlimited number of files, and the program keeps the opened objects in the memory. After a quick research I found Ergonomics in the 5.0 Java Virtual Machineand others saying on Windows machine the JVM defaults max heap size as 64MB
.
我正在Java 5上编写客户端Swing应用程序(图形字体设计器)。最近,我遇到了错误,因为我对内存使用并不保守。用户可以打开无限数量的文件,程序将打开的对象保存在内存中。经过快速研究,我发现5.0 Java 虚拟机中的 Ergonomics和其他人说在 Windows 机器上 JVM 默认最大堆大小为.java.lang.OutOfMemoryError: Java heap space
64MB
Given this situation, how should I deal with this constraint?
鉴于这种情况,我应该如何处理这种约束?
I could increase the max heap sizeusing command lineoption to java, but that would require figuring out available RAM and writing some launching program or script. Besides, increasing to some finitemax does not ultimatelyget rid of the issue.
我可以使用java 的命令行选项增加最大堆大小,但这需要找出可用的 RAM 并编写一些启动程序或脚本。此外,增加到某个有限的最大值并不能最终解决这个问题。
I could rewrite some of my code to persist objects to file system frequently (using database is the same thing) to free up the memory. It could work, but it's probably a lot work too.
我可以重写我的一些代码来频繁地将对象持久化到文件系统(使用数据库是同样的事情)以释放内存。它可以工作,但也可能需要很多工作。
If you could point me to details of above ideas or some alternatives like automatic virtual memory, extending heap size dynamically, that will be great.
如果您可以向我指出上述想法的详细信息或一些替代方案,例如自动虚拟内存、动态扩展堆大小,那就太好了。
采纳答案by Ben Childs
Ultimately you always have a finite max of heap to use no matter what platform you are running on. In Windows 32 bit this is around 2GB
(not specifically heap but total amount of memory per process). It just happens that Java chooses to make the default smaller (presumably so that the programmer can't create programs that have runaway memory allocation without running into this problem and having to examine exactly what they are doing).
最终,无论您在什么平台上运行,您始终可以使用有限的最大堆。在 Windows 32 位中,这是大约2GB
(不是专门的堆,而是每个进程的总内存量)。碰巧的是,Java 选择使默认值变小(大概是为了让程序员无法创建具有失控内存分配的程序,而不会遇到这个问题并且必须准确地检查他们在做什么)。
So this given there are several approaches you could take to either determine what amount of memory you need or to reduce the amount of memory you are using. One common mistake with garbage collected languages such as Java or C# is to keep around references to objects that you no longerare using, or allocating many objects when you could reusethem instead. As long as objects have a reference to them they will continue to use heap space as the garbage collector will not delete them.
因此,鉴于您可以采用多种方法来确定您需要多少内存或减少您正在使用的内存量。垃圾收集语言(例如 Java 或 C#)的一个常见错误是保留对不再使用的对象的引用,或者分配许多可以重用的对象。只要对象有对它们的引用,它们就会继续使用堆空间,因为垃圾收集器不会删除它们。
In this case you can use a Java memory profiler to determine what methods in your program are allocating large number of objects and then determine if there is a way to make sure they are no longer referenced, or to not allocate them in the first place. One option which I have used in the past is "JMP" http://www.khelekore.org/jmp/.
在这种情况下,您可以使用 Java 内存分析器来确定程序中的哪些方法正在分配大量对象,然后确定是否有办法确保它们不再被引用,或者首先不分配它们。我过去使用过的一个选项是“JMP” http://www.khelekore.org/jmp/。
If you determine that you are allocating these objects for a reason and you need to keep around references (depending on what you are doing this might be the case), you will just need to increase the max heap size when you start the program. However, once you do the memory profiling and understand how your objects are getting allocated you should have a better idea about how much memory you need.
如果您确定出于某种原因分配这些对象并且您需要保留引用(这可能取决于您在做什么),那么您只需要在启动程序时增加最大堆大小。但是,一旦您进行了内存分析并了解了您的对象是如何分配的,您就应该对需要多少内存有了更好的了解。
In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.
一般来说,如果您不能保证您的程序将在一定数量的内存中运行(可能取决于输入大小),您将始终遇到这个问题。只有在用尽所有这些之后,您才需要考虑将对象缓存到磁盘等。此时您应该有一个很好的理由说“我需要 Xgb 的内存”,并且您无法通过改进来解决它您的算法或内存分配模式。一般来说,这通常只适用于在大型数据集(如数据库或某些科学分析程序)上运行的算法,然后缓存和内存映射 IO 等技术变得有用。
回答by Dave Webb
Run Java with the command-line option -Xmx
, which sets the maximumsize of the heap.
使用命令行选项运行 Java,该选项-Xmx
设置堆的最大大小。
回答by kohlerm
Yes, with -Xmx
you can configure more memory for your JVM.
To be sure that you don't leak or waste memory. Take a heap dump and use the Eclipse Memory Analyzerto analyze your memory consumption.
是的,-Xmx
您可以为 JVM 配置更多内存。确保您不会泄漏或浪费内存。进行堆转储并使用Eclipse Memory Analyzer分析您的内存消耗。
回答by Leigh
If you need to monitor your memory usage at runtime, the java.lang.management
package offers MBeans
that can be used to monitor the memory pools in your VM (eg, eden space, tenured generation etc), and also garbage collection behaviour.
如果您需要在运行时监控内存使用情况,该java.lang.management
软件包提供MBeans
可用于监控 VM 中的内存池(例如,eden 空间、tenured generation 等)以及垃圾收集行为。
The free heap space reported by these MBeans will vary greatly depending on GC behaviour, particularly if your application generates a lot of objects which are later GC-ed. One possible approach is to monitor the free heap space after each full-GC, which you may be able to use to make a decision on freeing up memory by persisting objects.
这些 MBean 报告的可用堆空间将因 GC 行为而有很大差异,特别是如果您的应用程序生成了许多稍后被 GC 处理的对象。一种可能的方法是在每次 full-GC 后监视空闲堆空间,您可以使用它来决定通过持久化对象来释放内存。
Ultimately, your best bet is to limit your memory retention as far as possible whilst performance remains acceptable. As a previous comment noted, memory is always limited, but your app should have a strategy for dealing with memory exhaustion.
最终,最好的办法是在性能仍然可以接受的情况下尽可能限制内存保留。正如之前的评论所指出的,内存总是有限的,但您的应用程序应该有处理内存耗尽的策略。
回答by David
Big caveat ---- at my office, we were finding that (on some windows machines) we could not allocate more than 512m for Java heap. This turned out to be due to the Kaspersky anti-virus product installed on some of those machines. After uninstalling that AV product, we found we could allocate at least 1.6gb, i.e, -Xmx1600m
(m is mandatory other wise it will lead to another error "Too small initial heap") works.
大警告 ---- 在我的办公室,我们发现(在某些 Windows 机器上)我们不能为 Java 堆分配超过 512m 的空间。结果证明这是由于其中一些机器上安装了卡巴斯基反病毒产品。卸载那个 AV 产品后,我们发现我们可以分配至少 1.6gb,即 -Xmx1600m
(m 是强制性的,否则会导致另一个错误“初始堆太小”)工作。
No idea if this happens with other AV products but presumably this is happening because the AV program is reserving a small block of memory in every address space, thereby preventing a single really large allocation.
不知道其他 AV 产品是否会发生这种情况,但可能这是因为 AV 程序在每个地址空间中保留了一小块内存,从而防止了一次真正的大分配。
回答by Thorbj?rn Ravn Andersen
Note that if you need this in a deployment situation, consider using Java WebStart (with an "ondisk" version, not the network one - possible in Java 6u10 and later) as it allows you to specify the various arguments to the JVM in a cross platform way.
请注意,如果您在部署情况下需要它,请考虑使用 Java WebStart(使用“磁盘”版本,而不是网络版本 - 在 Java 6u10 及更高版本中可能),因为它允许您在交叉中指定 JVM 的各种参数平台方式。
Otherwise you will need an operating system specific launcher which sets the arguments you need.
否则,您将需要一个特定于操作系统的启动器来设置您需要的参数。
回答by mwangi
I read somewhere else that you can try - catch java.lang.OutOfMemoryError and on the catch block, you can free all resources that you know might use a lot of memory, close connections and so forth, then do a System.gc()
then re-try whatever you were going to do.
我在其他地方读到你可以尝试 - 捕获 java.lang.OutOfMemoryError 并在 catch 块上,你可以释放你知道可能使用大量内存的所有资源,关闭连接等等,然后做一个System.gc()
然后重新尝试任何事情你要做。
Another way is this although, i don't know whether this would work, but I am currently testing whether it will work on my application.
另一种方法是,虽然我不知道这是否可行,但我目前正在测试它是否适用于我的应用程序。
The Idea is to do Garbage collection by calling System.gc() which is known to increase free memory. You can keep checking this after a memory gobbling code executes.
想法是通过调用 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();
回答by SoulWanderer
If you keep on allocating & keeping references to object, you will fill up any amount of memory you have.
如果您继续分配和保留对对象的引用,您将填满您拥有的任何内存量。
One option is to do a transparent file close & open when they switch tabs (you only keep a pointer to the file, and when the user switches tab, you close & clean all the objects... it'll make the file change slower... but...), and maybe keep only 3 or 4 files on memory.
一种选择是在他们切换选项卡时关闭并打开透明文件(您只保留指向文件的指针,当用户切换选项卡时,您关闭并清理所有对象......它会使文件更改变慢...但是...),并且可能只在内存中保留 3 或 4 个文件。
Other thing you should do is, when the user opens a file, load it, and intercept any OutOfMemoryError, then (as it is not possible to open the file) close that file, clean its objects and warn the user that he should close unused files.
您应该做的另一件事是,当用户打开文件,加载它并拦截任何 OutOfMemoryError 时,然后(因为无法打开该文件)关闭该文件,清理其对象并警告用户他应该关闭未使用的文件。
Your idea of dynamically extending virtual memory doesn't solve the issue, for the machine is limited on resources, so you should be carefull & handle memory issues (or at least, be carefull with them).
您动态扩展虚拟内存的想法并不能解决问题,因为机器资源有限,因此您应该小心处理内存问题(或者至少要小心处理它们)。
A couple of hints i've seen with memory leaks is:
我在内存泄漏方面看到的一些提示是:
--> Keep on mind that if you put something into a collection and afterwards forget about it, you still have a strong reference to it, so nullify the collection, clean it or do something with it... if not you will find a memory leak difficult to find.
--> 请记住,如果您将某些内容放入集合中然后忘记它,您仍然对它有很强的引用,因此请取消集合,清理它或对其进行处理...如果没有,您会发现一个内存泄漏很难发现。
--> Maybe, using collections with weak references (weakhashmap...) can help with memory issues, but you mustbe carefull with it, for you might find that the object you look for has been collected.
--> 也许,使用带有弱引用的集合(weakhashmap...)可以帮助解决内存问题,但是您必须小心使用它,因为您可能会发现您要查找的对象已被收集。
--> Another idea i've found is to develope a persistent collection that stored on database objects least used and transparently loaded. This would probably be the best approach...
--> 我发现的另一个想法是开发一个持久性集合,该集合存储在最少使用和透明加载的数据库对象上。这可能是最好的方法......
回答by allenhwkim
You could specify perproject how much heap space your project wants
您可以为每个项目指定您的项目需要多少堆空间
Following is for Eclipse Helios/Juno/Kepler:
以下是针对Eclipse Helios/Juno/Kepler 的:
Right mouse click on
鼠标右键点击
Run As - Run Configuration - Arguments - Vm Arguments,
then add this
然后添加这个
-Xmx2048m
回答by Soumya Sandeep Mohanty
I have faced same problem from java heap size.
我在 Java 堆大小方面遇到了同样的问题。
I have two solutions if you are using java 5(1.5).
如果您使用的是 java 5(1.5),我有两个解决方案。
just install jdk1.6 and go to the preferences of eclipse and set the jre path of jav1 1.6 as you have installed.
Check your VM argument and let it be whatever it is. just add one line below of all the arguments present in VM arguments as -Xms512m -Xmx512m -XX:MaxPermSize=...m(192m).
只需安装 jdk1.6 并转到 eclipse 的首选项并设置您已安装的 jav1 1.6 的 jre 路径。
检查你的 VM 参数,让它成为任何东西。只需在 VM 参数中存在的所有参数下面添加一行作为 -Xms512m -Xmx512m -XX:MaxPermSize=...m(192m)。
I think it will work...
我认为它会起作用...