是否可以在java中捕获内存不足异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1692230/
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
Is it possible to catch out of memory exception in java?
提问by jy.
I'm developing a program that would require huge amount of memory, and I want to catch when out-of-memory exception happens. I had heard this is not possible to do, but curious if there is any development on this end.
我正在开发一个需要大量内存的程序,我想在发生内存不足异常时进行捕获。我听说这是不可能的,但很好奇这方面是否有任何发展。
采纳答案by ChssPly76
It's not an exception; it's an error: java.lang.OutOfMemoryError
这也不例外。这是一个错误:java.lang.OutOfMemoryError
You cancatch it as it descends from Throwable:
您可以在它从 Throwable 下降时捕获它:
try {
// create lots of objects here and stash them somewhere
} catch (OutOfMemoryError E) {
// release some (all) of the above objects
}
However, unless you're doing some rather specific stuff (allocating tons of things within a specific code section, for example) you likely won't be able to catch it as you won't know where it's going to be thrown from.
但是,除非您正在做一些相当具体的事情(例如,在特定的代码部分中分配大量的东西),否则您可能无法捕捉到它,因为您不知道它将从哪里抛出。
回答by Keith Randall
Sure, catching OutOfMemoryError is allowed. Make sure you have a plan for what to do when it happens. You will need to free up some memory (by dropping references to objects) before allocating any more objects, or you will just run out of memory again. Sometimes the mere act of unwinding the stack a few frames will do that for you, some times you need to do something more explicit.
当然,捕捉 OutOfMemoryError 是允许的。确保你有一个计划,当它发生时该怎么做。在分配更多对象之前,您需要释放一些内存(通过删除对对象的引用),否则您将再次耗尽内存。有时仅将堆栈展开几帧的行为就可以为您做到这一点,有时您需要做一些更明确的事情。
回答by Suraj Chandran
It's possible:
这是可能的:
try {
// tragic logic created OOME, but we can blame it on lack of memory
} catch(OutOfMemoryError e) {
// but what the hell will you do here :)
} finally {
// get ready to be fired by your boss
}
回答by jai
It is possible to catch Anyexception. Just write
可以捕获任何异常。写就好了
try{
// code which you think might throw exception
}catch(java.lang.Throwable t){
// you got the exception. Now what??
}
Ideally you are not supposed to catch java.lang.Error
exceptions. Not catching such exceptions, and letting the application to terminate might be the best solution when they occur. If you think that you can very well handle such Error's, then go ahead.
理想情况下,您不应该捕获java.lang.Error
异常。不捕获此类异常,并在它们发生时让应用程序终止可能是最佳解决方案。如果您认为您可以很好地处理此类错误,请继续。
回答by Peter Lawrey
It is possible, but if you run out of heap its not very useful. If there are resources which can be freed you better off using SoftReference or WeakReference to such resources and their clean-up will be automatic.
这是可能的,但如果你用完了堆,它不是很有用。如果有可以释放的资源,您最好对这些资源使用 SoftReference 或 WeakReference,它们的清理将是自动的。
I have found it useful if you run out of direct memory before this doesn't trigger a GC automatically for some reason. So I have had cause to force a gc if I fail to allocate a direct buffer.
我发现如果在出于某种原因不会自动触发 GC 之前耗尽直接内存,它会很有用。因此,如果我未能分配直接缓冲区,我就有理由强制执行 gc。
回答by Stephen C
You can catch and attempt to recover from OutOfMemoryError (OOM) exceptions, BUT IT IS PROBABLY A BAD IDEA... especially if your aim is for the application to "keep going".
您可以捕获并尝试从 OutOfMemoryError (OOM) 异常中恢复,但这可能是一个坏主意……尤其是如果您的目标是让应用程序“继续运行”。
There are a number of reasons for this:
有许多的原因:
As others have pointed out, there are better ways to manage memory resources than explicitly freeing things; i.e. using SoftReference and WeakReference for objects that could be freed if memory is short.
If you wait until you actually run out of memory before freeing things, your application is likely to spend more time running the garbage collector. Depending on your JVM version and on your GC tuning parameters, the JVM can end up running the GC more and more frequently as it approaches the point at which will throw an OOM. The slowdown (in terms of the application doing useful work) can be significant. You probably want to avoid this.
If the root cause of your problem is a memory leak, then the chances are that catching and recovering from the OOM will not reclaim the leaked memory. You application will keep going for a bit then OOM again, and again, and again at ever reducing intervals.
正如其他人所指出的,有比显式释放内容更好的管理内存资源的方法;即,如果内存不足,可以将 SoftReference 和 WeakReference 用于可以释放的对象。
如果您等到真正用完内存再释放内容,您的应用程序可能会花更多时间运行垃圾收集器。根据您的 JVM 版本和 GC 调整参数,JVM 最终会越来越频繁地运行 GC,因为它接近将引发 OOM 的点。放缓(就应用程序做有用的工作而言)可能是显着的。你可能想避免这种情况。
如果问题的根本原因是内存泄漏,那么从 OOM 中捕获和恢复很可能不会回收泄漏的内存。您的应用程序将继续运行一段时间,然后一次又一次地 OOM,一次又一次,以不断减少的间隔。
So my advice is NOT attempt to keep going from an OOM ... unlessyou know:
所以我的建议是不要试图从 OOM 中继续前进……除非你知道:
- where and why the OOM happened,
- that there won't have been any "collateral damage", and
- that your recovery will release enough memory to continue.
- OOM发生的地点和原因,
- 不会有任何“附带损害”,并且
- 您的恢复将释放足够的内存以继续。
回答by bitflung
just throwing this out there for all those who ponder why someone might be running out of memory: i'm working on a project that runs out of memory frequently and i have had to implement a solution for this.
只是把这个扔给那些思考为什么有人可能会耗尽内存的人:我正在做一个经常耗尽内存的项目,我不得不为此实施一个解决方案。
the project is a component of a forensics and investigation app. after collecting data in the field (using very low memory footprint, btw) data is opened in our investigation app. one of the features is to perform a CFG traversal of any arbitrary binary image that was captured in the field (applications from physical memory). these traversals can take a long time, but produce very helpful visual representations of the binary that was traversed.
该项目是取证和调查应用程序的一个组成部分。在现场收集数据后(使用非常低的内存占用,顺便说一句)数据在我们的调查应用程序中打开。其中一项功能是对现场捕获的任意二进制图像(来自物理内存的应用程序)执行 CFG 遍历。这些遍历可能需要很长时间,但会生成所遍历二进制文件的非常有用的视觉表示。
to speed the traversal process, we try to keep as much data in physical memory as possible, but the data structures grow as the binary grows and we cannot keep it ALL in memory (the goal is to use a java heap less than 256m). so what do i do?
为了加快遍历过程,我们尝试在物理内存中保留尽可能多的数据,但是数据结构随着二进制文件的增长而增长,我们不能将其全部保留在内存中(目标是使用小于 256m 的 java 堆)。那我该怎么办?
i created disk-backed versions of LinkedLists, Hashtables, etc. these are drop-in replacements for their counterparts and implement all the same interfaces so they look identical from the outside world.
我创建了 LinkedLists、Hashtables 等的磁盘支持版本。这些是它们对应物的直接替代品,并实现了所有相同的接口,因此它们从外部世界看起来是相同的。
the difference? these replacement structures cooperate with each other, catching out of memory errors and requesting that the least recently used elements from the least recently used collection be freed from memory. freeing the element dumps it to disk in temporary file (in the system provided temp directory) and marks a placeholder objects as "paged-out" in the proper collection.
区别?这些替换结构相互配合,捕获内存错误并请求从内存中释放最近最少使用集合中最近最少使用的元素。释放元素会将其转储到临时文件中的磁盘(在系统提供的临时目录中),并将占位符对象标记为适当集合中的“paged-out”。
there are PLENTY of reasons you might run out of memory in a java app - the root of most of these reasons is either one or both of: 1. App runs on a resource constrained machine (or attempts to limit resource usage by limiting heap size) 2. App simply requires large amounts of memory (image editing was suggested, but how about audio and video? what about compilers like in my case? how about long-term data collectors without non-volatile storage?)
在 Java 应用程序中可能会耗尽内存的原因有很多 - 大多数这些原因的根源是其中一个或两个: 1. 应用程序在资源受限的机器上运行(或尝试通过限制堆大小来限制资源使用) ) 2. 应用程序只需要大量内存(建议编辑图像,但音频和视频怎么样?像我这样的编译器怎么样?没有非易失性存储的长期数据收集器怎么样?)
-bit
-少量
回答by Hardcoded
It is possible to catch an OutOfMemoryError
(It's an Error
, not an Exception
), but you should be aware, that there is no way to get a defined behaviour.
You may even get another OutOfMemoryError while trying to catch it.
可以捕获一个OutOfMemoryError
(它是一个Error
,而不是一个Exception
),但您应该意识到,没有办法获得定义的行为。
在尝试捕获它时,您甚至可能会遇到另一个 OutOfMemoryError。
So the better way is to create/use memory aware Caches. There are some frameworks out there (example: JCS), but you can easily build your own by using SoftReference. There is a small article about how to use it here. Follow the links in the article to get more informations.
所以更好的方法是创建/使用内存感知缓存。有一些框架(例如:JCS),但您可以使用SoftReference轻松构建自己的框架。有一个关于如何使用它的小文章在这里。按照文章中的链接获取更多信息。
回答by Adam Goode
There is probably at least one good time to catch an OutOfMemoryError, when you are specifically allocating something that might be way too big:
当您专门分配可能太大的东西时,可能至少有一个好时机来捕获 OutOfMemoryError:
public static int[] decode(InputStream in, int len) throws IOException {
int result[];
try {
result = new int[len];
} catch (OutOfMemoryError e) {
throw new IOException("Result too long to read into memory: " + len);
} catch (NegativeArraySizeException e) {
throw new IOException("Cannot read negative length: " + len);
}
...
}