Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a bad practice to catch Throwable?

People also ask

Why catching throwable instead of hierarchy wise exception classes is a bad idea?

Throwable is a 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, nobody knows what kind of Error this method is going to throw, and until you know what is the problem, how can you resolve that.

Is it bad practice to catch all exceptions?

Also when you catch all exceptions, you may get an exception that cannot deal with and prevent code that is upper in the stack to handle it properly. The general principal is to catch the most specific type you can. catch(Exception) is a bad practice because it catches all RuntimeException (unchecked exception) too.

Should you catch errors Java?

Please note that the Java Virtual Machine throws errors to indicate severe problems from which it can't recover, such as lack of memory and stack overflows, among others. Thus, we must have a very, very good reason to catch an error!


You need to be as specific as possible. Otherwise unforeseen bugs might creep away this way.

Besides, Throwable covers Error as well and that's usually no point of return. You don't want to catch/handle that, you want your program to die immediately so that you can fix it properly.


This is a bad idea. In fact, even catching Exception is usually a bad idea. Let's consider an example:

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
    inputNumber = 10; //Default, user did not enter valid number
}

Now, let's say that getUserInput() blocks for a while, and another thread stops your thread in the worst possible way ( it calls thread.stop() ). Your catch block will catch a ThreadDeath Error. This is super bad. The behavior of your code after catching that Exception is largely undefined.

A similar problem occurs with catching Exception. Maybe getUserInput() failed because of an InterruptException, or a permission denied exception while trying to log the results, or all sorts of other failures. You have no idea what went wrong, as because of that, you also have no idea how to fix the problem.

You have three better options:

1 -- Catch exactly the Exception(s) you know how to handle:

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
    inputNumber = 10; //Default, user did not enter valid number
}

2 -- Rethrow any exception you run into and don't know how to handle:

try {
    doSomethingMysterious();
} catch(Exception e) {
    log.error("Oh man, something bad and mysterious happened",e);
    throw e;
}

3 -- Use a finally block so you don't have to remember to rethrow:

 Resources r = null;
 try {
      r = allocateSomeResources();
      doSomething(r);
 } finally {
     if(r!=null) cleanUpResources(r);
 }

Also be aware that when you catch Throwable, you can also catch InterruptedException which requires a special treatment. See Dealing with InterruptedException for more details.

If you only want to catch unchecked exceptions, you might also consider this pattern

try {
   ...
} catch (RuntimeException exception) {
  //do something
} catch (Error error) {
  //do something
}

This way, when you modify your code and add a method call that can throw a checked exception, the compiler will remind you of that and then you can decide what to do for this case.


straight from the javadoc of the Error class (which recommends not to catch these):

 * An <code>Error</code> is a subclass of <code>Throwable</code> 
 * that indicates serious problems that a reasonable application 
 * should not try to catch. Most such errors are abnormal conditions. 
 * The <code>ThreadDeath</code> error, though a "normal" condition,
 * is also a subclass of <code>Error</code> because most applications
 * should not try to catch it. 

 * A method is not required to declare in its <code>throws</code> 
 * clause any subclasses of <code>Error</code> that might be thrown 
 * during the execution of the method but not caught, since these 
 * errors are abnormal conditions that should never occur. 
 *
 * @author  Frank Yellin
 * @version %I%, %G%
 * @see     java.lang.ThreadDeath
 * @since   JDK1.0

It's not a bad practice if you absolutely cannot have an exception bubble out of a method.

It's a bad practice if you really can't handle the exception. Better to add "throws" to the method signature than just catch and re-throw or, worse, wrap it in a RuntimeException and re-throw.