When to Catch Java.Lang.Error

When to catch java.lang.Error?

Generally, never.

However, sometimes you need to catch specific errors.

If you're writing framework-ish code (loading 3rd party classes), it might be wise to catch LinkageError (no class def found, unsatisfied link, incompatible class change).

I've also seen some stupid 3rd-party code throwing subclasses of Error, so you'll have to handle those as well.

By the way, I'm not sure it isn't possible to recover from OutOfMemoryError.

Catching all java.lang.Error for logging purposes and allowing them to work their way up the stack

You said: "I tried this..."

    } catch (Throwable e) {
e.printStackTrace();
throw e;
}

You should try instead:

    } catch (Error e) {
e.printStackTrace();
throw e;
}

Errors are not checked exceptions. You don't have to declare them in any method signature. Just put that in your outermost method and it will do what you want.

Edit:

If you want to also catch and rethrow Exception, let's think about it. You have three kinds of Throwable: Error, Exception and RuntimeException. Error and RuntimeException are not checked, but Exception which are not RuntimeException are.

So, you can do the same thing for RuntimeException as we do for Error:

    } catch (RuntimeException e) {
e.printStackTrace();
throw e;
} catch (Error e) {
e.printStackTrace();
throw e;
}

And what about Exception who are not RuntimeException? The thing to understand is that these are checked exceptions and if they are not declared in the methods that the code is calling, then they will not be thrown. So you don't need to catch/rethrow them. If some of the methods called actually throw such an exception, then you will have to catch/rethrow it and mark your method as throwing that exception, but you would have to do that anyway since they are coming from methods the outer method is calling.

Catching Java errors

Other than giving advice on how to technically overcome the problem, I'd like to take a moment and explain why it's considered "bad practice" in the first place.

Let's start off by clarifying what the Error class is.


In java, errors and exceptions (which are the main types) are thrown. Throwing one of the above is done by using the throw keyword. Every class which extends the basic java.lang.Throwable can be thrown.

There are two classes which inherit from the basic Throwable class: Exception and Error. The difference between those two is explained in their documentations:

An Error is a subclass of Throwable that indicates serious
problems that a reasonable application should not try to catch. Most
such errors are abnormal conditions.
[...]

Source

The class Exception and its subclasses are a form of Throwable
that indicates conditions that a reasonable application might want
to catch.

Source


As explained above, errors and exceptions are separated because of their different origins. An Error normally indicates a problem, which the application can not recover from. Therefore, they should not be caught.

The same is true for a RuntimeException, but it is used to indicate a problem with a high-level layer (e.g. methods). Whereas the Error indicates a low-level problem (e.g. the runtime).


So, now that you understood that you shall only catch exceptions and errors which you are able to recover from, the answer to your question should be clear.

Yes, it's perfectly reasonable to catch the UnsatisfiedLinkError, because your application can recover from it.


I covered the above (in more detail and with examples) and some extended information in an article on my Blog.

Is it appropriate to catch java.lang.ExceptionInInitializerError in multi-threaded application?

It is only appropriate to catch this error if you are going to print an error message and then immediately terminate the application.

The problem is that the class whose initialization has failed will be permanently stuck, as will any other class whose initialization depends on the class. This will lead to more exceptions whenever something attempts to use one of these classes.

The only possibility of fixing this is if all of the affected classes are loaded via a child classloader ... that can be abandoned / replaced with a new one. This is possible in theory, but often impossible in practice.

My recommendation would be NOT do the initialization in a static initializer if you anticipate that the initialization may fail due to something that the user does. Instead, do the initialization explicitly; e.g. using lazy initialization the first time that a Singleton getInstance method is called.

Why is the Catch(Exception) almost always a bad Idea?

Because when you catch exception you're supposed to handle it properly. And you cannot expect to handle all kind of exceptions in your code. 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.



Related Topics



Leave a reply



Submit