Is it a bad practice to catch Throwable?

96,895

Solution 1

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.

Solution 2

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);
 }

Solution 3

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.

Solution 4

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

Solution 5

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.

Share:
96,895

Related videos on Youtube

ktulinho
Author by

ktulinho

Software Engineer with 12 years of experience developing, deploying and maintaining client and server applications. Ability to design and develop applications using Object Oriented concepts, Software Engineering concepts and methodologies such as Scrum and Agile. Specialties: Java EE, Java SE, Maven, Git, SQL, IntelliJ, Databases and a bit of DevOps. Continuously improving skills and knowledge through courses, articles and technical conferences. Interested by: Serverless, Cloud and Server-Side Applications; Desktop and mobile application design, development, usability and improving user experience; New technologies such as IoT, Machine Learning, VR and video games!

Updated on October 31, 2020

Comments

  • ktulinho
    ktulinho over 3 years

    Is it a bad practice to catch Throwable?

    For example something like this:

    try {
        // Some code
    } catch(Throwable e) {
        // handle the exception
    }
    

    Is this a bad practice or we should be as specific as possible?

  • gawi
    gawi about 11 years
    There are situations where catching Error and continue is appropriate. Ex: In a servlet, if you enconter an OutOfMemoryError because a specific request happen to eat all the memory, you can try to continue since the objects will be GC after the request is handled. Same goes for an assertion error. You don't shutdown an application because something went wrong in a request.
  • bmauter
    bmauter almost 11 years
    How do you know what was allocated and what wasn't prior to the OOME? All bets are off once you get that, even inside a J2EE container like Tomcat or JBoss.
  • Raedwald
    Raedwald almost 11 years
    Or use a better written library?
  • DNA
    DNA almost 11 years
    Indeed, if you have the choice ;-)
  • Yuriy Nakonechnyy
    Yuriy Nakonechnyy almost 10 years
    Totally agree - there are absolutely legitimate cases for handling all Throwable instances - e.g. for custom exception logging.
  • Dean Hiller
    Dean Hiller about 9 years
    We have had NoSuchMethodError and thankfully did not take out all our customers by shutting down the server as it happened two weeks after deployment. ie. We always have a catchall catching Throwable and making a best effort to handle and send error to customer. After all, there are lots of types of Error that are recoverable in that it may only affect 1 of 1000 customers.
  • assylias
    assylias almost 9 years
    "you want your program to die immediately so that you can fix it properly" => if your program dies, how do you know what happened? Catching Throwable/Error to log the problem is a reasonable thing to do...
  • BalusC
    BalusC almost 9 years
    @assylias: Only if your runtime environment doesn't already do that for some reason (e.g. badly configured stdout/logging framework). And you still need to rethrow it.
  • assylias
    assylias almost 9 years
    @BalusC If you have a standalone application (main entry point) then it won't log anything automatically unless you ask it to do so with an uncaught exception handler or a catch-all block... Within a web or application server I agree that it it is not necessary.
  • Philip Whitehouse
    Philip Whitehouse over 8 years
    @assylias A stand-alone application will throw a fatal error to stderr.
  • Andrew Norman
    Andrew Norman over 8 years
    thats the biggest problem with catching throwables and re-throwing them. it really makes an impossible interface for all the methods upstream in the stack. They either have to deal with a throwable or have an unusable throws throwable signature that others will have to deal with.
  • Kirill Gamazkov
    Kirill Gamazkov about 8 years
    +1 for stating that even catching Exception is no good. At least there is an ThreadInterruptedException which requires special care (in short - after catching it, you have to set thread's interrupted status back to 'true')
  • Vadiraj Purohit
    Vadiraj Purohit almost 8 years
    @BalusC +1 for your answer. Fail fast is the best approach. Do not catch Exception or Throwable. Because catching these can lead to hard to find bugs in the code.
  • Vadiraj Purohit
    Vadiraj Purohit almost 8 years
    Saw the code in these links. Throwable is not only the one that is catched! There are other exceptions catched too before Throwable.
  • Alireza Fattahi
    Alireza Fattahi almost 8 years
    @developer101 of course, but they do catch throwable, which is what is this question about
  • amdev
    amdev over 7 years
    I Know it's just for illustrate your words but I think you can check with a regex if your user input is Alphanumeric or what format you need and don't use try catch everywhere every time.
  • Eduardo
    Eduardo over 5 years
    This is a bogus argument as there are very important reasons to catch Throwable and very important software does this: github.com/spring-projects/spring-framework/… github.com/apache/tomcat/…
  • BalusC
    BalusC over 5 years
    @Eduardo: the average developer who has this question doesn't write "very important software".
  • Eduardo
    Eduardo over 5 years
    @BalusC You should reflect that in your answer. So crappy software should not catch Throwable ever, but good software can.
  • BalusC
    BalusC over 5 years
    @Eduardo: No, I won't.
  • Philip Rego
    Philip Rego over 5 years
    How am I suppose to know if there's a Error/Throwable if I don't catch it? I didn't see anything in the logs. Java EE app. Just spent days stuck not knowing what the problem was until I added this catch.
  • Petr Újezdský
    Petr Újezdský almost 5 years
    I consider the option #2 as bad practice. Imagine 10 chained calls with log & rethrow. If you look at the log file, you won't be happy. The exception is logged 10 times making logs very hard to read. IMHO much better is to do throw new Exception("Some additional info, eg. userId " + userId, e);. This will be logged in one nice exception with 10 causes.
  • SSharma
    SSharma about 2 years
    Arthimetic Exception is an Exception and not an error. Look here: rollbar.com/blog/java-exceptions-hierarchy-explained/….