When to catch java.lang.Error?
Asked Answered
I

16

123

In what situations should one catch java.lang.Error on an application?

Indian answered 9/12, 2008 at 13:56 Comment(1)
See also #2679830Aronow
G
109

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.

Gustafsson answered 9/12, 2008 at 14:12 Comment(5)
That I had to do exactly to load DLLs, that would fail if they were not correctly configured. Not a fatal error in case of this application.Cognizable
It sometimes makes sense to catch OutOfMemoryError - for example when you are creating large array lists.Latin
@SpaceTrucker: does that approach work well in multithreaded applications, or is there a significant risk that smaller allocations in other threads fail because of it? … presumably only if your arrays were just small enough to be allocated, but left nothing for anyone else.Crowberry
@Crowberry I'm not sure about that. This would require some real world statistical samples. I thought I had seen such code, but can't remember where it was.Latin
It is very possible to recover from OutOfMemoryError if by throwing that error large amounts of memory have been unlocked for the GC to process. It however indicates a major flaw in the code or JVM setup, so it should not be done lightly.Tatterdemalion
D
54

Never. You can never be sure that the application is able to execute the next line of code. If you get an OutOfMemoryError, you have no guarantee that you will be able to do anything reliably. Catch RuntimeException and checked Exceptions, but never Errors.

http://pmd.sourceforge.net/rules/strictexception.html

Diptych answered 9/12, 2008 at 14:0 Comment(6)
Never say never. we have testing code that does an "assert false;" then catches the AssertionError to makes sure that the -ea flag is set. Other than that...yeah, probably never ;-)Trichite
How about a server application that hands requests off to worker threads. Might it not make sense to catch Throwable on the worker thread to trap any errors, and at least try and log what's gone wrong?Maximin
Never...except when you absolutely need to. Never is a strong word and there are always exceptions to the rules. If you are building a framework, it's not that unlikely that you will have to catch and handle certain errors, even if it is just to log.Wiburg
How about errors e.g. NoSuchMethodError that is coming from third party library methods?Buschi
@OutlawProgrammer Just for the record, there are other ways to do the same test: boolean assertionsEnabled = false; assert assertionsEnabled = true;Diplopia
The catching and suppressing of Errors (or repackaging them as something else) is the biggest cause of rogue undead zombie threads running untethered in production systems wrecking havocFurness
B
16

Generally you should always catch java.lang.Error and write it to a log or display it to the user. I work in support and see daily that programmers cannot tell what has happened in a program.

If you have a daemon thread then you must prevent it being terminated. In other cases your application will work correctly.

You should only catch java.lang.Error at the highest level.

If you look at the list of errors you will see that most can be handled. For example a ZipError occurs on reading corrupt zip files.

The most common errors are OutOfMemoryError and NoClassDefFoundError, which are both in most cases runtime problems.

For example:

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

can produce an OutOfMemoryError but it is a runtime problem and no reason to terminate your program.

NoClassDefFoundError occur mostly if a library is not present or if you work with another Java version. If it is an optional part of your program then you should not terminate your program.

I can give many more examples of why it is a good idea to catch Throwable at the top level and produce a helpful error message.

Blenheim answered 5/3, 2009 at 12:29 Comment(6)
i'd suspect its better in those cases to fail the daemon with proper alerts then to have the possibility of it staying alive as some etherial ghost on a failed jvm where it might give the false pretext that it is really alive and doing somethingFurness
OutOfMemoryError is not a runtime error there's no guarantee that the application can recover from it. If you are lucky, you may get OOM in new byte[largeNumber] but if that allocation wasn't enough to cause OOM, it could be triggered in next line or next thread. This is runtime problem because if length is untrusted input it should be validated before calling new byte[].Blumenthal
NoClassDefFoundError can occur anywhere, as it is invoked when compiled java code cannot find a class. If your JDK is misconfigured it can trigger from trying to use java.util.* class and it is practically impossible to program against it. If you are optionally including a dependency, you should use ClassLoader to check whether it exists, which throws ClassNotFoundException.Blumenthal
ZipError indicates that the jar file containing classes is a corrupted zip file. This is quite serious issue and at this point you cannot trust any code that gets executed and it would be irresponsible thing for attempting to "recover" from it.Blumenthal
In general, It may be helpful to catch java.lang.Error or java.lang.Throwable at top level and attempt to do something with it - say log an error message. But at that point there is no guarantee that this will get executed. If your JVM is OOMing, attempting to log may allocate more Strings which triggers another OOM.Blumenthal
I agree too, though catching Error is considered bad practice but catching at highest level seems logical when you are advised not to show ANY technical stack trace in client facing UI, only some predefined messages. Problem is bug tracking tool PMD, Sonar etc keep insulting you :(Gossoon
A
16

In multithreaded environment, you most often want to catch it! When you catch it, log it, and terminate whole application! If you don't do that, some thread that might be doing some crucial part would be dead, and rest of the application will think that everything is normal. Out of that, many unwanted situations can happen. One smallest problem is that you wouldn't be able to easily find root of the problem, if other threads start throwing some exceptions because of one thread not working.

For example, usually loop should be:

try {
   while (shouldRun()) {
       doSomething();
   }
}
catch (Throwable t) {
   log(t);
   stop();
   System.exit(1);
}

Even in some cases, you would want to handle different Errors differently, for example, on OutOfMemoryError you would be able to close application regularly (even maybe free some memory, and continue), on some others, there is not much you can do.

Asterisk answered 7/3, 2009 at 16:39 Comment(2)
Catching OutOfMemoryError and continuing rather than existing promptly is unwise because your program is then in an undefined state.Aronow
calling system,exit on catching a throwable has the unintended consequence of killing everything running on the JVM and not just the application in question. Not usually a good practice for web applications that might be hosted on an app server with other web applications (not to mention it would impact the app server itself).Furness
P
9

Very rarely.

I'd say only at the top level of a thread in order to ATTEMPT to issue a message with the reason for a thread dying.

If you are in a framework that does this sort of thing for you, leave it to the framework.

Punchboard answered 9/12, 2008 at 14:15 Comment(0)
I
7

Almost never. Errors are designed to be issues that applications generally can't do anything about. The only exception might be to handle the presentation of the error but even that might not go as planned depending on the error.

Invertebrate answered 9/12, 2008 at 13:59 Comment(0)
M
6

An Error usually shouldn't be caught, as it indicates an abnormal condition that should never occur.

From the Java API Specification for the Error class:

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. [...]

A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.

As the specification mentions, an Error is only thrown in circumstances that are Chances are, when an Error occurs, there is very little the application can do, and in some circumstances, the Java Virtual Machine itself may be in an unstable state (such as VirtualMachineError)

Although an Error is a subclass of Throwable which means that it can be caught by a try-catch clause, but it probably isn't really needed, as the application will be in an abnormal state when an Error is thrown by the JVM.

There's also a short section on this topic in Section 11.5 The Exception Hierarchy of the Java Language Specification, 2nd Edition.

Misplay answered 9/12, 2008 at 14:18 Comment(0)
J
6

If you are crazy enough to be creating a new unit test framework, your test runner will probably need to catch java.lang.AssertionError thrown by any test cases.

Otherwise, see other answers.

Jamilla answered 10/12, 2008 at 20:44 Comment(0)
F
5

And there are a couple of other cases where if you catch an Error, you have to rethrow it. For example ThreadDeath should never be caught, it can cause big problem is you catch it in a contained environment (eg. an application server) :

An application should catch instances of this class only if it must clean up after being terminated asynchronously. If ThreadDeath is caught by a method, it is important that it be rethrown so that the thread actually dies.

Fasten answered 9/12, 2008 at 14:9 Comment(1)
Which is actually a non-issue because you simply do not catch Errors.Corin
S
4

Very, very rarely.

I did it only for one very very specific known cases. For example, java.lang.UnsatisfiedLinkError could be throw if two independence ClassLoader load same DLL. (I agree that I should move the JAR to a shared classloader)

But most common case is that you needed logging in order to know what happened when user come to complain. You want a message or a popup to user, rather then silently dead.

Even programmer in C/C++, they pop an error and tell something people don't understand before it exit (e.g. memory failure).

Southeast answered 9/12, 2008 at 14:28 Comment(0)
C
4

In an Android application I am catching a java.lang.VerifyError. A library that I am using won't work in devices with an old version of the OS and the library code will throw such an error. I could of course avoid the error by checking the version of OS at runtime, but:

  • The oldest supported SDK may change in future for the specific library
  • The try-catch error block is part of a bigger falling back mechanism. Some specific devices, although they are supposed to support the library, throw exceptions. I catch VerifyError and all Exceptions to use a fall back solution.
Cutwork answered 14/3, 2013 at 6:17 Comment(0)
C
3

it's quite handy to catch java.lang.AssertionError in a test environment...

Chalaza answered 27/11, 2013 at 1:53 Comment(2)
What value are you trying to add?Trod
adding the value of a test suite not abortingChalaza
S
2

Ideally we should not handle/catch errors. But there may be cases where we need to do, based on requirement of framework or application. Say i have a XML Parser daemon which implements DOM Parser which consumes more Memory. If there is a requirement like Parser thread should not be died when it gets OutOfMemoryError, instead it should handle it and send a message/mail to administrator of application/framework.

Soothe answered 5/5, 2014 at 18:22 Comment(0)
L
1

ideally we should never catch Error in our Java application as it is an abnormal condition. The application would be in abnormal state and could result in carshing or giving some seriously wrong result.

Leahy answered 26/1, 2011 at 6:23 Comment(0)
T
1

It might be appropriate to catch error within unit tests that check an assertion is made. If someone disables assertions or otherwise deletes the assertion you would want to know

Tadd answered 19/8, 2012 at 20:35 Comment(0)
A
1

There is an Error when the JVM is no more working as expected, or is on the verge to. If you catch an error, there is no guarantee that the catch block will run, and even less that it will run till the end.

It will also depend on the running computer, the current memory state, so there is no way to test, try and do your best. You will only have an hasardous result.

You will also downgrade the readability of your code.

Appomattox answered 23/4, 2013 at 16:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.