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.
-
2Asking how to handle running out of memory is not quite the same as asking whether it is possible to catch an `OutOfMemoryError`. So this is not quite a duplicate of [How to handle OutOfMemoryError in Java](https://stackoverflow.com/questions/511013/how-to-handle-outofmemoryerror-in-java). – Raedwald Jul 19 '20 at 08:52
9 Answers
It's not an exception; it's an error: java.lang.OutOfMemoryError
You can catch it as it descends from 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.

- 99,456
- 24
- 206
- 195
-
18Plus, there's likely no easy way for you to recover from it if you do catch it. – matt b Nov 07 '09 at 06:45
-
@matt b - in the specific case where you're **able** to catch it you're presumably trying to control your memory consumption and thus would be able to release some / all of it. But generally speaking you're right, of course. – ChssPly76 Nov 07 '09 at 06:48
-
1@ChssPly76 (and others) - please read my answer to understand why trying to manage memory consumption by catching OOME's would be a **BAD IDEA**. – Stephen C Jul 10 '12 at 05:59
-
thank you @ChssPly76 ,but Stephen where there is no option so we use this try catch – Bald bcs of IT Aug 30 '13 at 14:11
-
@BaldbcsofIT - Your assertion that there is no alternative is incorrect. There is always an alternative: restart the JVM. – Stephen C May 04 '14 at 04:00
-
Stephen is correct, start your JVM with: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${DUMP_PATH} -XX:OnOutOfMemoryError="kill -9 %p" when it dies restart it. – user2179737 Dec 22 '16 at 18:29
-
As opposed to some other commenters, it does have a realistic use case when catching OOM error is the desired solution. Imagine a web service which fails to handle the large data the client just has sent. In this case, responding a HTTP error code to the client is fine. The request of the client won't be served but the server stays alive. Much better than a dead web service. – Csongor Halmai Feb 22 '20 at 14:40
-
@CsongorHalmai - If you have to catch and recover from an OOME, you will have first triggered a full GC which will (typically) take a long time. Sending requests that cause OOMEs could be an effective DoS attack ... whether it is done with deliberate intent to harm or by accident. Limiting requests sizes is a better solution. – Stephen C May 06 '20 at 14:27
-
@StephenC you not necessarily are able to filter the memory-intensive requests simply by the size of the request. I can easily imagine a small request that needs a lot of memory while another request in similar size needs just a small RAM for creating the response. Say, the request contains a URL if a jpg image which is processed by the server. Two jpgimages can have 50 character long URL while ...1.jpg is 10x10 pixels small while ...2.jpg has a lot more data in it. The second one _may_ cause OOM exception but not necessarily will. – Csongor Halmai May 07 '20 at 15:27
-
So, in some cases the defensive code needs to be inside the application's request processing logic. But the same strategy applies. If certain requests / request types are able to trigger OOMEs at will, change things so that the request is stopped before the OOM condition happens ... or else your server is vulnerable to DoSing. – Stephen C May 07 '20 at 23:16
-
@ChssPly76 What if I want to catch it just to send a metric to the monitor system and then rethrew it? – Elad Cohen Feb 02 '22 at 08:51
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
}

- 24,433
- 12
- 63
- 94
-
12There *is* at least one reasonable thing which you could be doing which causes an OOME and is recoverable: Loading a very large image. The only thing in the try block is a call to ImageIO.read(), and you're showing the user a dialog telling them that the image is too large in the catch block. Just saying... – uckelman Nov 07 '09 at 10:18
-
3@uckelman That's a wrong approach, unless your app is single threaded. The thing is that even though your image-loading-thread catches OOME, but the other threads dont know about this and can get an OOME too – Suraj Chandran Oct 04 '12 at 11:19
-
5@SurajChandran: The OOME caused by attempting to load a very large image will be due to attempting to allocate a very large `byte[]` or `int[]`. You get an OOME from that because the allocation fails, not because you are actually out of memory---hence it won't cause a problem on other threads. – uckelman Oct 04 '12 at 11:34
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".
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.
So my advice is NOT attempt to keep going from an OOM ... unless you know:
- 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.

- 698,415
- 94
- 811
- 1,216
-
What if I want to catch it just to send a metric to the monitor system and then rethrew it? – Elad Cohen Feb 02 '22 at 08:52
-
That may be OK. It depends. The concern is that the infrastructure (in the JVM) for talking to the monitoring system might itself have been damaged by the out of memory state. So even sending the metric could lock up things. – Stephen C Feb 02 '22 at 10:02
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.
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?
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.
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.
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?)
-bit

- 1
- 1
- 2
-
This sort of logic sounds like a perfect usecase for the 'Reference' classes like WeakReference https://stackoverflow.com/a/1692369/29924 – Ben Page Apr 01 '20 at 16:32
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.
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.

- 6,476
- 2
- 22
- 20
-
2"there is no way to get a defined behaviour": because `OutOfMemoryError` can be thrown anywhere, including in places that could leave your program in an inconsistent state. See http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror-guarantees – Raedwald Jan 10 '12 at 12:52
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.
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.

- 525,659
- 79
- 751
- 1,130
-
1This answer addresses the primary use case that would drive wanting to do this. The answer should be much higher up. – Steve Steiner Apr 24 '18 at 19:50
There is probably at least one good time to catch an OutOfMemoryError, when you are specifically allocating something that might be way too big:
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);
}
...
}

- 7,380
- 3
- 29
- 33
-
Does this code work reliably? I have exactly this case, but I really dont want the app to crash. I guess the alternative is if(len>someConservativeSize) throw new IOException("too long"); – Quantum7 Nov 17 '11 at 22:55
-
5This approach works well in C++, but I suspect not so well in Java, because the connection between `new` and `OutOfMemoryError` is indirect. If the allocation only just fits into memory, there could be a mysterious `OutOfMemoryError` some time later. – Raedwald Jan 10 '12 at 12:55
It is possible to catch Any exception. 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.

- 21,519
- 31
- 89
- 120
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.

- 22,985
- 2
- 35
- 54
-
1Your plan will have to include a strategy for dealing with the possibility that your program is in an inconsistent state; see http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror-guarantees – Raedwald Jan 10 '12 at 12:56