3

I have a class the implements A which will run a certain method of class B. There is a requirement that this A should never crash when running this operation (which is not possible, right?).

To reduce the chance of crashing I'm catching Throwable around the operation, like so:

public void method(B b)
{
    try
    {
        b.operation
    }
    catch(Throwable e)
    {
        //Log e
        //Clean up stuff
    }
}

My questions are:

  • Would this actually help in reducing crashes caused by any thrown Error?
  • Is it a good idea to ever catch an Error?
gnat
  • 21,442
  • 29
  • 112
  • 288
Adam
  • 295
  • 1
  • 8
  • The `ExecutorService` will not stop running if your code throws an exception, it's just the `Runnable` will stop and not be rescheduled. Other than that - Do you really need this particular module to continue working even if the rest of the app just went haywire? – Ordous Oct 06 '14 at 14:22
  • 1
    possible duplicate of [Defensive Programming vs Exception Handling?](http://programmers.stackexchange.com/questions/139171/defensive-programming-vs-exception-handling) –  Oct 06 '14 at 14:26
  • @Ordous Damn I forgot about that. I was trying to use ExecutorService as an example because I can't share real code due to company policy. I'll edit the question :p – Adam Oct 06 '14 at 14:26
  • 1
    Also see [here](http://programmers.stackexchange.com/q/164256/53019) and much of the questions [here](http://programmers.stackexchange.com/questions/tagged/exception-handling?sort=votes&pageSize=50) –  Oct 06 '14 at 14:27
  • @Ordous I know it's weird by I don't make the requirements and have no influence on them. So if they say don't crash this module that means I have to do the best to not crash this module. I've been explicitly told this. – Adam Oct 06 '14 at 14:28
  • @Adam Perhaps it is then better to use a separate VM for the "uncrashable" module and communicate with the main app via signals? The nature of `Error`s is such that most of the time the actual place it's being thrown from doesn't matter all that much. – Ordous Oct 06 '14 at 14:31
  • see also [Recommend a design pattern/approach to exposing/tolerating/recovering from system errors, Exception handling (e.g.s in Java, C++, Perl, PHP)](http://programmers.stackexchange.com/questions/109297/recommend-a-design-pattern-approach-to-exposing-tolerating-recovering-from-syste) – gnat Oct 06 '14 at 14:32

4 Answers4

11

Simple Answers: No and no.

For example catching an OutOfMemoryError can be bad as without memory what could you do?

Also all other errors are most likely indicate some more serious error where you can do nothing.

For reference see the errors in the package java.lang and decide for every one what you will do when you catch it. If you're happy you will find that perhaps every tenth error could be handled by you.

Uwe Plonus
  • 1,310
  • 9
  • 16
  • But are there any other Errors that can be "handled"? – Adam Oct 06 '14 at 14:22
  • 3
    @Adam No, there are none. One of the reasons they are **not** exceptions is stated right on the `Error` class - reasonable applications should not catch these. Another trait is that `Error`s are **not** local. For most exceptions all side effects are in the calling method, for an `Error` that is not the case. – Ordous Oct 06 '14 at 14:24
  • @Adam extended answer while you created the comment. – Uwe Plonus Oct 06 '14 at 14:25
  • Catching an OOM can often be perfectly reasonable and not a problem at all, when it's due to specific unsatisfiable allocation requests in a subtask. – Michael Borgwardt Oct 06 '14 at 14:32
  • @MichaelBorgwardt If you catch an `OOME` then you cannot create any new object in most cases. So it is difficult to do something useful in an object oriented language. Also all tips with allocating an _emergency_ array can fail as you cannot influence the garbage collector. – Uwe Plonus Oct 06 '14 at 14:35
  • 1
    Usually you'd catch an OOME at a pretty high level, with many objects going out of scope and freeing up space. And if the error was caused by a single oversized allocation request, then there really is no problem at all. – Michael Borgwardt Oct 06 '14 at 15:05
  • 3
    @MichaelBorgwardt actually is quite the opposite, catching an OOME might make some sense at low level (say, I am requesting a 30 MB+ buffer to load a video file). In that case, you can expect and deal with the error easily (just replacing it with an exception/could not load control code). If you just capture the error at high level, the state of the system would be unknown (it is unknown which operations failed), and the only realistic option would be "resetting" all of the program states. – SJuan76 Oct 06 '14 at 16:26
  • @SJuan76: of course it depends on the structure of the application, but many (especially servers) have no global shared state, or keep it in a database with transaction semantics. – Michael Borgwardt Oct 06 '14 at 17:48
  • I can recall a major issue we had last year where a background thread in our web app (not tied to Tomcat's thread pool) listens to a queue of work to do and ran into a StackOverflowError from a few rare data conditions involving recursion. The urgency wasn't with the StackOverflowError. That was a minor edge case. The problem was nobody could figure out why this queue processing would sometimes stop until app servers are restarted. Eventually, when we realized the StackOverflowError was occuring and we had a thread pool of 3 and it was after the 3rd task that we failed, we figured it out. – Brandon Oct 07 '14 at 19:09
  • All of which could have been avoided if instead of `catch (Exception e)`, we did `catch (Throwable t)`. – Brandon Oct 07 '14 at 19:09
  • 1
    So I agree that catching `Error`s is often futile, but contrary to some of the absolute statements here, there are legitimate circumstances to catch `Error`s. – Brandon Oct 07 '14 at 19:11
  • @Brandon I know that such absolute statements are sometimes wrong. But in general you should really know what you're doing when catching `Error`s as it can be much worse than let the server dying and restart it... – Uwe Plonus Oct 08 '14 at 05:27
3

When you encounter an Error, it typically means your program is now in an undefined state: a .class file is corrupted, or memory is completely full, or you've run into an internal bug in the JVM, or something of similar severity. Ask yourself: even if you catch the Error to prevent an immediate crash, is it meaningful to continue running under these circumstances? Can you trust the program to behave correctly afterward? What can you do to actually handle an Error once you catch it?

If your "never crash" requirement means "never stop executing", then by all means, log and continue. Clearly your client believes that a misbehaving program is better than a terminated one. But if "never crash" means "never stop functioning", you should focus your defensive efforts elsewhere to prevent the Error from occurring in the first place, let it terminate the program if it somehow occurs anyway, and configure your server to automatically restart the program if that happens.

Wyzard
  • 295
  • 1
  • 7
1

In general, you should NEVER catch things like Exception, Throwable, or Error, but only those specific subclasses of those that your application can reasonably be expected to handle and survive (or at least log something useful about before crashing).

Exception handling is supposed to be just that, handling error conditions and dealing with them in such a way that the application can continue running or report what happened before terminating.
It's not meant to be error masking, hiding problems and then just try to continue as if nothing happened. Not only will it rarely work (it will rear its ugly head somewhere else in the application soon, making the problem worse as now you have even more corruption in your state and/or data, but you now have a problem that's that much harder to track down and debug, and eventually fix.

jwenting
  • 9,783
  • 3
  • 28
  • 45
0

I won't write a java program without catching Throwable at the top level of every process. The caught error is (by definition) unexpected, and is a bug that needs to be logged and fixed. The errors you catch this way will surprise you, and you will never learn of them unless you make every possible attempt to get the word back from the real world to your development desk.

ddyer
  • 4,060
  • 15
  • 18