When to catch java.lang.Error?
Solution 1
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
.
Solution 2
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
Solution 3
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.
Solution 4
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.
Solution 5
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.
Raydan
Degree in Computer Science. In different degrees of experience, programmed with C++ C# Java Javascript Shell Script, VBScript, Jython, Python, Ruby, CSS, HTML, J2EE, WebSphere J2EE specific APIs, IBM CM specific APIs, Webservices, powershell etc. Working currently with planning, some analysis, some task automation, change management and execution. And obviously my fair share of bureaucracy big company work...
Updated on March 13, 2020Comments
-
Raydan about 4 years
In what situations should one catch
java.lang.Error
on an application? -
Bombe over 15 yearsWhich is actually a non-issue because you simply do not catch
Error
s. -
Tim Frey over 15 yearsNever 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 ;-)
-
Leigh over 15 yearsHow 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?
-
Xairoo over 15 yearsNever...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.
-
Mario Ortegón over 15 yearsThat 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.
-
SpaceTrucker about 11 yearsIt sometimes makes sense to catch OutOfMemoryError - for example when you are creating large array lists.
-
László Papp over 10 yearsWhat value are you trying to add?
-
PJTraill almost 9 years@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.
-
SpaceTrucker almost 9 years@PJTraill 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.
-
Raedwald over 8 yearsCatching
OutOfMemoryError
and continuing rather than existing promptly is unwise because your program is then in an undefined state. -
ha9u63ar over 8 yearsHow about errors e.g. NoSuchMethodError that is coming from third party library methods?
-
Andrew Norman over 8 yearsi'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 something
-
Andrew Norman over 8 yearscalling 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).
-
Jeeyoung Kim about 8 years
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 innew 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 iflength
is untrusted input it should be validated before callingnew byte[]
. -
Jeeyoung Kim about 8 years
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 usejava.util.*
class and it is practically impossible to program against it. If you are optionally including a dependency, you should useClassLoader
to check whether it exists, which throwsClassNotFoundException
. -
Jeeyoung Kim about 8 years
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. -
Jeeyoung Kim about 8 yearsIn general, It may be helpful to catch
java.lang.Error
orjava.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 moreString
s which triggers another OOM. -
supernova almost 8 yearsI 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 :(
-
shmosel over 7 years@OutlawProgrammer Just for the record, there are other ways to do the same test:
boolean assertionsEnabled = false; assert assertionsEnabled = true;
-
Jono over 6 yearsadding the value of a test suite not aborting
-
Ludger over 4 yearsI agree, at the highest level you should always catch throwable and try print it out. If your system is dead or something at least you tried to output the error. You do not gain anything by not trying to print it out. No matter the error.
-
TwoThe over 3 yearsIt 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.
-
Andrew Norman almost 2 yearsThe 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 havoc