How can I let the "Unchecked Exception" bubble and log?

So, quoting this page which is titled: A Blog about Disallowing Exception Handling and seems to be written (or at least should be approved) by Oracle ..

An unchecked exception should probably not be repeated and the correct answer usually does nothing, and let it bubble out of your method and through the execution stack. This is why it doesn't need to be quoted. Eventually, at a high level of execution, an exception must be logged.

I'm 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 offering here? I don't see a direct (or clear) way to catch exceptions at runtime (I don't understand why these aren't just thrown thrown exceptions ...) at higher levels, and I'm not sure how this suggested practice is helpful. It would make sense to me if it were about checked exceptions . Something like..

If a checked exception is thrown in a method that is impractical to repeat, the correct answer is for it to run and start the log.

+3


source to share


8 answers


You can also register a global ExceptionHandler that will handle exceptions that your code has not caught:

Thread.setDefaultUncaughtExceptionHandler

      



This exception handler could log everything that happened.

+1


source


First of all, this is general advice and it depends on the context. The idea behind this is that when a runtime exception (like NullPointerException

) is thrown , the system is usually in an undefined state, which means the rest of the code won't be guaranteed as expected, so it's best to stop everything.

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

This is not the case in your example, because everything is done in one thread, so an uncaught exception will effectively halt the entire program. In this case, you can 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, register and re-modify it.

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

      

Edit: catch Throwable

instead of Exception

, will catch tooError

Note. Dexterous throwing is usually a bad idea and should only be done with a specific purpose, not in general. See @RC. a comment.

+1


source


As I understand it, the documentation assumes that you have a generic high-level handler in your code that logs "unexpected" (unrecoverable?) Exceptions, 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 arithmetic log differently
         log("arith issue! "+aex.getMessage());
    } 
    catch (Exception ex) { //Otherwise do the best we can 
            log("unknown issue! "+ex.getMessage())
    } 
}

      

This way, there is still no way to recover, but at least before the process completes, you will have a chance to log the problem. You can also use Exception (or throwable) methods to get the stack trace and first causal exceptions in many cases - so there is a lot of additional useful information that can be logged.

0


source


How do I know what to register here? The method I am calling does not throw an exception.

As Joshua Bloch recommends in Effective Java

Use the Javadoc @throws tag to document every unchecked exception that a method can throw, but don't use the throw keyword to include unchecked exceptions in a method declaration

And if you are using method wrapping in a layered application, I can recommend using exception broadcasting :

Higher levels should catch lower level exceptions and throw exceptions instead, which can be explained in terms of higher level abstraction

See Effective Java Element 61

So, I think that for your example you should actually use something like:

try {
 bar();
} catch(NullPointerException e) {
 throw new HigherLevelException(...);
}

      

0


source


There is a very simple way to catch thrown exceptions since they are all subclasses, RuntimeException

or Error

:

public static void main(String[] args) {
    try {
        // your code
    } catch (RuntimeException | Error e) {
        // handle uncaught exceptions, e.g.
        e.printStackTrace();
    }
}

      

0


source


The most important rule about exceptions is that a method that cannot successfully complete its task must throw an exception.

Only if you can guarantee that your method task completes successfully, you should catch the exception inside your method (without rethrowing this or another exception). In my experience, this is only true in very specific situations, for example. if you have an alternative way to try, if some first try failed, or if you really really understand all the possible reasons for this particular class of exceptions you are about to catch.

Speaking of RuntimeExceptions, there are so many different types of RuntimeExceptions that one can hardly justify a statement like "When such an exception occurs in my code or a method called inside my code, it will not affect the result of my method - I can continue as if nothing occurred". Thus, you have to inform your caller that you have not completed your task, and the clearest way to do this is to resolve the exception by passing the exception, without declaring try / catch or throws, just relying on Java's default behavior.

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

, throws . : throws ( !) , RuntimeException (ex) .

Using, for example, a typical GUI application, your users will be grateful if a problem with one menu function does not cause the entire application to crash - perhaps other menu items may still work as expected. Thus, top-level commands or menu items are usually places where you can catch exceptions, tell the user something like "Oops!"

In your main / foo / bar / baz application, I don't see any place where continuing after an exception makes sense. Therefore, the entire program must be interrupted (which happens automatically in your case). If you want any error log to be logged to a file, install an uncaught exception handler, or wrap the main () body in a try / catch (Throwable t) block. You probably want every exception to be logged no matter what it is, so catch them all, which is why I suggest Throwable.

0


source


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

Use cases may vary. In my opinion, the most popular is that it doesn't make sense to catch the right of the exception at this point, or the corresponding handling has to be implemented at multiple levels (in terms of methods) above the method, by calling the one that threw the exception (sorry if that's not enough clear).

For example, a typical layout for a web application in java looks like this: you have a controller layer, a service layer, and a dao layer. The former is responsible for sending requests, the latter is for managing the business logic, and the latter is for the actual calls to the db. So here, for example, it often doesn't make sense to catch an exception in the service layer if something goes wrong in the dao layer. Unchecked exceptions can be used here. You log an exception and throw an Exception Exception, so it can be handled at some levels higher so that the user can get valuable feedback on how the application works.

If, in this case, you have thrown a thrown exception, you will need to rethrow it each level higher to align it to where it is actually handled. So there is no exception being thrown here to avoid copying and pasting that whole ugly try-catch block, reverse engineering the exception and adding a throws clause to the method.

-1


source


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 at the level of the baz () method. If I get you right.

-1


source







All Articles