Is there any point catching an out of memory error (java.lang.OutOfMemoryError) in Java?
9 Answers
Yes. Here are a few examples where it could make sense:
- if you want to handle it by gracefully closing your program
- if you want to display the problem to the user or log the error
- depending on your design, you might even be able to clear up memory and restore a working state
However, note that normally (unless you're at a spot where you'll be allocating tons of memory at once), you probably wouldn't specifically catch OutOfMemoryError for these cases, but rather do a catch Throwable all the way at the top in your main entry point.
2 Comments
No, catch Exception and RuntimeException, but hardly ever (changed from 'never') Error:
An Error is a subclass of
Throwablethat indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. TheThreadDeatherror, though a "normal" condition, is also a subclass ofErrorbecause most applications should not try to catch it.
Note:
I'm quoting the official Javadocs here. If you don't agree, tell Oracle, don't shoot the messenger :-)
5 Comments
As some other answers have pointed out, it is a bad idea to catch OutOfMemoryError and attempt to recover1. Rather than just repeating that the javadoc says you Error exceptions are not recoverable, I'll try to explain why.
In fact there are at least two solid reasons why OOME recovery is unwise:
The First Reason is that OOME's are typically the result of undiagnosed memory leaks. If your application catches and attempts to recover, the chances are that the leaked memory will still be reachable and hence still won't be reclaimed. So when your application starts doing things it is likely to leak more memory ... and run into another OOME. Sooner or later, the application grinds to a halt.
Since there is no way you can be absolutely sure that your application doesn't leak, OOME recovery is never going to be a solid, reliable answer.
The Second Reason is that when an OOME occurs, there is a chance that it will do damage to the execution state. It might cause threads to terminate, leaving other threads waiting for notifications that will never arrive, etc. It might occur in the middle of updating a critical application data structure or (possibly worse) a JVM data structure. If your application then attempts to recover, it might lock up, or (worse) it might manage to keep going with corrupted data, and produce unpredictable results.
Unless you perform a forensic analysis of your codebase, you can never be entirely sure that this kind of thing won't happen.
I won't say you should NEVER attempt to recover from an OOME, but in general it is a risky thing to do. And the more complex your application is, the harder it is to evaluate the risk.
1 - Here I am talking about catching OOME in an attempt to allow the application to continue running as before; i.e. to recover the application. Catching an OOME in order to perform (or trigger) an orderly shutdown is a different matter.
Comments
If you want to have a graceful shutdown which handles this case specificly.
You can also use it if you may have to allocate a large array and you want to gracefully degrade your system.
EDIT: An example of code where I used to check OOM if the stream was corrupted. I have since replace the len check to ensure the len is between 0 and 16 MB instead.
DataInputStream dis = new DataInputStream(socket.getInputStream());
public byte[] readBytes() {
int len = dis.readInt();
try {
byte[] bytes = new byte[len];
dis.readFully(bytes);
return bytes;
} catch(OutOfMemoryError e) {
log.error("Corrupt stream of len="+len);
closeSocket();
return null;
}
}
6 Comments
This has already been mentioned a number of times, but the replies indicate a few people are confused about this (common) recovery technique for an OutOfMemoryError. Check my post to What if new fails? for a demo of how to do it.
Comments
The only place I have done that was mobile development. You can ask user to close other applications in order to give your application ability to work properly. But that's not the case of Android development.
I don't see any other things you can do with the situation. May be, some appropriate logging or cleanup.
Comments
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.
1 Comment
This is one of the errors you should never catch. The reason for this is simple you will not be able to do anything about it at runtime. However if your application is regularly facing this error then you should consider the following strategies to mitigate this issue-
- Increase the memory available to the JVM by adding jvm args
-Xms1024m -Xmx1024m
If the errors still persist then use a profiler like JProfiler or a Eclipse MAT to analyze how much memory your application uses.
Move to a 64 bit system and increase the JVM memory even further.