Saturday, 7 June 2014

Why Catching Throwable or Error is bad?

We often hear advice that catching Throwable or Error is bad practice and Java developer should avoid catching these, but have you thought Why? If language allows you to catch anything which is instance of java.lang.Throwable, then what is the problem of catching them or their subclass java.lang.Error? If they are bad, shouldn't Java itself has prohibited them from catching?  Well this all looks good on theory, but not in real world programming. As I said before in Java Exception best practices post, Ideally you should never catch Throwable or in particular Error. There are several reasons why catching instance of java.lang.Throwable is bad idea, because in order to catch them you have to declare at your method signature e.g. public void doSomething() throws Throwable. When you do this, no body knows what kind of Error this method is going to throw, and until you know what is the problem, how can you resolve that. Main purpose of providing Exception handling mechanism is to handle error situation properly, but you can't a provide a solution which can solve all problems. That's why we have specific Exception classes e.g. FileNotFoundException, IllegalArgumentException, IOException and so on. So if you don't know how to resolve or handle error, there is no point catching Throwable, all it make your code hard to read and comprehend. Remember, each error handling code is driven by business/audit/reporting or quality requirement and catching Throwable just obscure those logics.


Some programmer catch Throwable and re-throw it by wrapping it into RuntimeException. Catching and re-throwing Exception after logging is OK but you must not rewrap the exception in a RuntimeException, and if you do make sure to preserve actual cause and stack-trace. Spring framework does lot of this checked to unchecked exception conversion, which makes your code free of boiler-plate but also posses challenge when you are going to debug any problem. When Spring framework prints stack trace for any issue, they are usually very long, combination of multiple exception and their cause, which actually buries the real issue down in the log file. If you are not careful, you may spend countless hours fixing bug at wrong place.

Should you Catch Throwable, Exception or Error
Similarly Error covers system exceptions that you can't do anything about and should let show up (for instance OutOfMemoryError, StackOverFlowError, ThreadDeath). Rethrowing them as a unchecked exception hides them and doesn't help the cause. It may even prevents handlers that really know how to deal with them, from seeing them. That's why code catching java.lang.OutOfMemoryError is of no use, apart from giving false impression to developer that by catching OutOfMemoryError and calling System.gc() may help Application to come out of the memory mess they have created.

Catching Exception is nearly as bad as catching Throwable. Exception covers all kinds of exceptions ranging from NullPointerException to  InterruptedException, which should never be caught lightly. If you think you are actually coding same handling logic for multiple exception e.g. FileNotFoundException or IOException, consider using JDK 7 improved Exception handling feature, which allows you to catch multiple Exceptions in same catch block. Benefit of using multi-catch block over catching Exception is, it is explicit, more readable and only catch what is required, and not masking other programming errors.

By the way in real world there are Exceptions :), Yes Exception on catching Throwable. There are cases, where you need to catch Throwable e.g. if an application has a requirement of constantly running and never going off, no matter what happens. In data driven and even based system, e.g. an order processing engine, if your system failed to process one order due to any exception, it should continue with next order to keep impact only with that order. Now catching Throwable provides you a safety net to catch anything which you have not excepted. Though this will not help you if your system is out of resources e.g. running out of memory, or running out of thread, it does prevent you from data errors, e.g. Encoding related issues,  and several others, which you have not thought about. By the way, if you catch Throwable, use it as safety net, not as your primary exception handling code and make sure to evolve and improve your exception handling code, as and when your safety net exposes new Exceptions. Let me know what is your thought on catching Error or Throwable? Have you ever catch Throwable in real world applications, and what did you learn from that.

No comments:

Post a Comment