3

So quoting from this page, which is titled: Exception-Handling Antipatterns Blog and seems to be written (or at least to be approved) by Oracle..

An unchecked exception probably shouldn't be retried, and the correct response is usually to do nothing, and let it bubble up out of your method and through the execution stack. This is why it doesn't need to be declared in a throws clause. Eventually, at a high level of execution, the exception should probably be logged.

I am not sure if I understand this. How can I log an unchecked exception? If I have something like:

public static void main(String args) {
    foo();
    // How do I know what to log here? The method I am calling
    // is not throwing an Exception. 
    // Do I just blindly catch(Exception ex)?
}

static void foo() {
    bar();
}

static void bar() {
    baz();
}

static void baz() {
    // I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
    throw new NullPointerException();
}

Can you help me understand what Oracle is suggesting here? I do not see any direct (or clear) way to catch runtime exceptions (I do not understand why it is not just called unchecked exceptions..) in higher levels and I am not sure how this suggested practice is useful. To me it would make more sense if it were talking about checked exceptions. Something like..

If a checked exception is thrown in a method that is not reasonable to be re-tried, the correct response is to let it bubble up and log..

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • Did you read https://stackoverflow.com/questions/6115896/java-checked-vs-unchecked-exception-explanation?rq=1 already? –  Jun 23 '17 at 14:04
  • @RC. Yes, thank you. I am not asking about Checked and Unchecked Exceptions, I am trying to understand what Oracle is suggesting regarding Unchecked Exceptions.. – Koray Tugay Jun 23 '17 at 14:08
  • If I try to run your code, it actually raises an exception – Asew Jun 23 '17 at 14:12
  • the correct response is to let it bubble up meaning, you use try and catch, if exception arises so you simply ex.printstacktrace(); to log it – nafas Jun 23 '17 at 14:20
  • @KorayTugay strange, because this answer seems to fit your question: https://stackoverflow.com/a/6116051/180100 –  Jun 23 '17 at 16:20

8 Answers8

3

You can also register a global ExceptionHandler that will handle the Exceptions that were not caught by your code:

Thread.setDefaultUncaughtExceptionHandler

This exception handle could then log whatever occured.

Florian S.
  • 386
  • 1
  • 12
1

First of all, this is a general advice and it depends on the context. The idea behind it is that when a runtime exception occurs (ex. NullPointerException), the system is usually in an indeterministic state, meaning the rest of the code is not be guaranteed to execute as expected, so it's better to stop everything.

In most cases, your code will run in a separate thread and the exception will only stop the current thread, while the rest of the program keeps running.

This is not the case in your example, because everything is executed in a single thread, so the uncaught exception will effectively stop the whole program. In this scenario you might want to catch the exception and handle it.

public static void main(String args) {
    try {
        foo();
    catch(Throwable t) {
        t.printStackTrace(); // log exception
        // handle the failure
    }
}

You can also catch the exception earlier on, log and rethrow it further.

static void bar() {
    try {
        baz();
    catch (Throwable t) {    // catch
        t.printStackTrace(); // log
        throw t;             // rethrow further
    }
}

Edit: catch Throwable instead of Exception, will also catch Error

Note: Catching throwable is usually a bad idea, and should only be done with a specific purpose, not in general case. See @RC.'s comment.

noscreenname
  • 3,314
  • 22
  • 30
  • When we are using external libraries, we do not know whether the method we are calling will be throwing a Runtime Exception or not. It is easy for you to surround the baz method with a try - catch here, but do we blindly surround all methods we call like this? – Koray Tugay Jun 23 '17 at 14:24
  • @KorayTugay If its a critical part of your program, and you don't want it killed by a bug in an external library, then yes, it's justifiable. Everything depends on whether you want to continue with execution knowing that `baz()` failed. – noscreenname Jun 23 '17 at 14:28
  • catching Throwable is not a good idea. see https://stackoverflow.com/questions/6083248/is-it-a-bad-practice-to-catch-throwable for example –  Jun 23 '17 at 16:20
0

As I understand it the documentation is suggesting that you have a generic handler at a high level of your code that logs such 'unexpected' (unrecoverable?) exceptions just as the comments in your main method suggest. So it might look something like this

public static void main(String args) {
    try {
      foo();
    } 
    catch (ArithmeticException aex) { //if it's arithmetic log differently
         log("arith issue! "+aex.getMessage());
    } 
    catch (Exception ex) { //Otherwise do the best we can 
            log("unknown issue! "+ex.getMessage())
    } 
}

So there is still no path to recovery but at least before the process ends you get a chance to log the issue. You can also use the methods of Exception (or throwable) to get the stack trace and first causal exceptions in many case - so there is is a lot of extra useful information that might be logged.

Elemental
  • 7,365
  • 2
  • 28
  • 33
  • this will prevent exceptions from 'bubbling up and will not end you process (except if you foo throws an error). You need to rethrow the exception after you log it. – noscreenname Jun 23 '17 at 14:54
  • @noscreenname but this is the top level so the main method ends here anyway. – Elemental Jul 06 '17 at 16:46
0

How do I know what to log here? The method I am calling is not throwing an Exception.

As Joshua Bloch recommends in the Effective Java

Use the Javadoc @throws tag to document each unchecked exception that a method can throw, but do not use the throws keyword to include unchecked exceptions in the method declaration

And if you are using method wrapping in multilayered app i can recommend use exception translation:

Higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction

See Effective Java item 61

So i think for your example actually you should use something like:

try {
 bar();
} catch(NullPointerException e) {
 throw new HigherLevelException(...);
}
Mike Adamenko
  • 2,944
  • 1
  • 15
  • 28
0

There is a very straightforward way to catch unchecked exceptions, since they are all subclasses of RuntimeException or Error:

public static void main(String[] args) {
    try {
        // your code
    } catch (RuntimeException | Error e) {
        // handle uncaught exceptions, e.g.
        e.printStackTrace();
    }
}
Aloso
  • 5,123
  • 4
  • 24
  • 41
0

The most important guideline regarding exceptions is that a method that couldn't sucessfully complete its task should throw an exception.

Only if you can guarantee successful completion of your method's task, you should catch an exception inside your method (without re-throwing this or another exception). From my experience that's only true in very specific situations, e.g. if you have an alternative way to try if some first attempt fails, or if you really really understand all possible causes of this specific Exception class that you are about to catch.

Speaking about RuntimeExceptions, there are so many different types of RuntimeException that you can hardly justify an assertion like "When such an exception arises in my code or a method called from inside my code, that won't affect the outcome of my method - I can continue just as if nothing happened." So, you should signal to your caller that you failed to fulfill your task, and the clearest way to do that is to let the exception ripple through, without try/catch block or throws declaration, just relying on Java's default behaviour.

In my opinion, the same reasoning applies to nearly all kinds of exceptions, not only RuntimeExceptions.

The difference with checked exceptions is that you have to declare them in the throws clause of your method. Then you have two choices: list the exception in the throws clause of your method (and all parent methods as well!) or catch the exception, wrap it in a new RuntimeException(ex), and throw that from your method.

With e.g. a typical GUI application, your users will be grateful if a problem in one menu function won't crash the whole application - probably other menu items might still work as expected. So, top-level commands or menu items are typically the places where to catch exceptions, tell the user something like "Oops!", log the exception to some file for later inspection, and allow the user to continue with another action.

In your main/foo/bar/baz application, I don't see a place where continuing after an exception makes sense. So the whole program should be aborted (which happens automatically in your case). If you want some error logging to a file, then establish an uncaught exception handler or wrap the body of main() in a try / catch(Throwable t) block. You'll probably want every exception logged, whatever type it is, so catch them all, and that's why I'm suggesting Throwable.

Ralf Kleberhoff
  • 6,990
  • 1
  • 13
  • 7
-1

You can catch them just like any other exception with try-catch block. But the benefit is that you don't have to.

Use cases can vary. To my mind, the most popular is when it doesn't make sense to catch the exception right in that place or the appropriate handling should be implemented several levels (in terms of methods) higher than the method, calling the one throwing the exception (sorry, if that is not clear enough).

For example, the typical web application layout in java is as follows: you have a layer of controllers, a layer of services and a layer of dao. First one is responsible for dispatching requests, the second one is for managing business logic and the last one makes actual calls to db. So here for example it often doesn't make much sense to catch the exception in service layer if something goes wrong on the dao level. Here unchecked exceptions can be used. You log an exception and throw an unchecked exception so it could be handled some levels above for a user to get valuable feedback of work of the application.

If in this case you throw a checked exception you will have to rethrow it every level above just to bubble up it to the place of the actual handling. So here the unchecked exception is better to use in order not to copy and paste all that ugly try-catch block, rethrowing an exception and add the throws clause to the method.

Dmitry Senkovich
  • 5,521
  • 8
  • 37
  • 74
-1
public static void main(String[] args) {
        try {
            foo();
        }
        catch(NullPointerException e){
               System.out.println("NullPointerException in main.");
        }        
    }

    static void foo() {
        bar();
    }

    static void bar() {
        baz();
    }

    static void baz() {
        // I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
        throw new NullPointerException();
    }

OUTPUT :

NullPointerException in main.

Basically the error is expected at a higher level, so there is no need to catch it on the baz() method level. If I understood correctly.

Asew
  • 374
  • 2
  • 13