Should I catch OutOfMemoryError? [duplicate]

2019-01-28 09:36发布

This question already has an answer here:

The general advice is that you should not catch java.lang.Error except in special circumstances, see Is it a bad practice to catch Throwable? for instance.

My situation is that I have a program which sometimes runs out of memory and throws java.lang.OutOfMemoryError. Although there's no recovery from this I do want to know it happened, so I wish to see something in the log and a non-zero exit code. So is something like this adviseable?

public static void main(String[] args)
{
    try
    {
        ...
    }
    catch (Exception e)
    {
        e.printStackTrace();
        System.exit(1);
    }
    catch (OutOfMemoryError e)
    {
        e.printStackTrace();
        System.exit(1);
    }
}

Another program is similar except that it may be one particular thread that is consuming all the memory. In this case if that thread exits it is possible to continue processing, again all I really want is to see a log and to ultimately have a non-zero exit code. So should I catch the OutOfMemoryError in that threads run method?

4条回答
Rolldiameter
2楼-- · 2019-01-28 09:55

There is perfect sense in having an exception barrier at the very top of your call stack, catching and logging all Throwables. In server-side code this is in fact the norm. If you make sure to catch the OutOfMemoryError only at that level, and not anywhere lower, there is a very large chance that it will not harm your system: as the call stack unwinds, all the objects created to serve the request will become unreachable. Since it is very likely that the OOME occurred precisely in the thread which was inflicting the strongest memory pressure on the system, all that memory will be reclaimed and the rest of the system will be able to breathe again.

Yes, technically there's always a chance to get an OOME inside a finally block, causing a resource leak or worse; or inside some code which was modifying a long-lived, global structure, breaking its invariants, but it is quite unlikely in practice.

When deciding on your policy for OOMEs keep in mind that your application is subject to many unpredictable factors which are more or less likely to deteriorate its stability. OOME is just another point in that spectrum, and typically its risk impact is not particularly high.

查看更多
Rolldiameter
3楼-- · 2019-01-28 09:55

It is common to catch it, but only at the highest level in your thread. The easiest way is to use an uncaughtexception handler. This is a function that is called when an exception is thrown. At that point you can log it and tell the user why you are exiting the application.

查看更多
Anthone
4楼-- · 2019-01-28 09:56

The general rule is: any exception should be caught by the module which is most competent to react adequately. If current method does not know what to do, it should let the exception pass through, until reaching main() or run() methods. Those methods cannot hope there are more competent methods, so they can catch and log or watever.

查看更多
三岁会撩人
5楼-- · 2019-01-28 10:08

In the example above, I think it is a good idea so you can control how your program shutdown. If you don't catch this error, other threads can continue to run incorrectly (The error is only thrown in one thread) It also give a exit code when a calling shell can check. I would use a different exit code for this error.

In general OOME is not guaranteed to be recoverable but doesn't guarantee your program will shut down either.

查看更多
登录 后发表回答