I rather say that fail fast and not catching Throwable is a good practice. But in case unhandled exception in request processor like StackOverflowError, the task may be stopped. And that doesn't always sound good. I'd rather catch StackOverflowError over and over, but some tasks might be processed. What is good practice here?
There is no "good practice" or "best practice"1 about catching Error and hence Throwable.
On the one hand, a JVM can recover successfully from some kinds of Error in some circumstances. For example, if you are running "task" on a single thread that doesn't interact with other threads (directly or indirectly), then that thread can safely recover from a StackOverflowError and possibly2 a OutOfMemoryError.
On the other hand, many Error subclasses indicate that the application or JVM is in a state where recovery is not possible, or not practical:
A class loading or initialization Error means that certain classes will be an unusable state. An application that depends the class won't be able to proceed.
If an application that uses notify / wait or higher level synchronization constructs gets (say) an OutOfMemoryError error on one thread, it is liable to leave other threads waiting for notifications, etc that may never arrive.
My recommendation would be to heed the implied advice in the javadoc for Error and not to catch and attempt recover from Error or its subclasses. If you attempt to recover, allow for the possibility that the application may "wedge".
1 - Actually, there is not "best practice" at all; see https://www.satisfice.com/blog/archives/5164
2 - This depends on the root cause. If the root cause is a memory leak elsewhere in your codebase, then recovery is a bad idea. The OOME is likely to recur ... with increasing frequency.
This is from the javadoc of Error :
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
I usually follow this rule to avoid suppressing real unexpected errors that should be fixed.
You mentionned StackoverflowError, if you have this kind of error, there's probably a problem with your algorithm and your code should be optimized.
If you know that a specific error is likely to be thrown and you're okay with that, you can catch it.
However if you don't expect it, it's better to raise the alarm ASAP and deal with it.
Good practice is catch scheduled jobs, write log about exception, metrics and(optional) reschedule it.
Also, sometimes your thread will be stoped/destroyed (hello spring schedulers) cause you receive some sort of exception, that not critical to your job...
Related
used thread.sleep when exception occurs in my application
if any thing exception occured in any one of the thread it should wait for some time and have to try again
what i am facing the issue means for 100 request if exception occurs for 50 means that should be wait for some time and after try again if any
exception occurs means it should also wait till success
am feeling this going to affect the performance and system usage.
Please let me know your suggestions. Is it better to create new thread if any exception occurs?
Or Any other way?
Retrying on exception isn't a bad idea, but you should make sure that:
The exception is transient (i.e. you have reasons to believe it may
succeed on retry, like a network error)
You have ways to prevent retrying forever (like "max retry")
You don't overload the system by too frequent retries by e.g. using exponential back-off strategy (or even just a reasonably long wait time)
Exception to rule 2 is possible (sometimes you do want stuff to retry forever).
From the question, I understand that, you are talking about RunTimeExceptions.
1) Firstly I would like to suggest that, you should examine the code areas which may really throw the exceptions at run time i.e processing of files.
2) another thing is that you have to handle this scenarios so that exception cases are reduced. i.e first check file is available then only try to read it, check permissions before writing it etc. In this way frequency of retrying may be reduced.
3) If both above actions fails, means the situation which can never be handled such as services are down etc., you can retry the considering all necessary aspects like - MAX try, MAX time out foe which you are re-trying, leave the attempt after certain amount of try OR time etc.
Hope this helps.
I have been reading the JLS and I encountered the section 11.1.3. Asynchronous Exceptions from which I quote:
Most exceptions occur synchronously as a result of an action by the
thread in which they occur, and at a point in the program that is
specified to possibly result in such an exception. An asynchronous
exception is, by contrast, an exception that can potentially occur at
any point in the execution of a program.
And
Asynchronous exceptions occur only as a result of:
[...]
An internal error or resource limitation in the Java virtual machine that prevents it from implementing the semantics of the
Java programming language. In this case, the asynchronous exception
that is thrown is an instance of a subclass of VirtualMachineError.
Is it possible to catch such exceptions for logging purposes or notification (because I believe such thing is unrecoverable)? How can I achieve such thing?
You can catch such exceptions just like any other exception. The only problem is that they may occur at any place in your program, so catching them reliably is hard. You would basically have to wrap the run method of all threads and the main method in a try..catch block, but you can't do that for threads you don't control (like the Swing EDT, or threads for timers etc.).
Also catching any subclass of Error is usually not recommended, because the JVM may be in an unstable state, which might lead to a further failure (for example in the case of OutOfMemoryError, you might not even have enough memory to to the exception handling). However, logging would be a valid reason for catching Errors in my eyes.
My suggested solution would be to use an uncaught exception handler for this by setting it as the default exception handler. In this handler you will get all exceptions and errors, if they are not caught anywhere in the code, and you can try to log them.
There is no point of catching these exceptions (Subclasses of VirtualMachineError) as you have no indecattion in which state the pogram is at the point, the Doc saies about Virtual Machine Errors:
A Java virtual machine implementation throws an object that is an
instance of a subclass of the class VirtualMethodError when an
internal error or resource limitation prevents it from implementing
the semantics described in this chapter. This specification cannot
predict where internal errors or resource limitations may be
encountered and does not mandate precisely when they can be reported.
so assuming you get in an OutOfMemoryError or an UnknownError there isnt much you can do about it, and once your vritualmashine doesnt work properly you cant provide the user anyhelp as your program isnt working properly as well, besides you have no idea at what time, point, and reason it happends since its not a code error that was caused from your program.
Some code simply call
catch (InterruptedException ex) {}, why?
This is usually a sign that the developer didn't know how to handle the Exception and thus just ignored it.
This is the sort of bad behaviour that results in some saying checked exceptions are a failed experiment. IMHO Developers should just learn to handle exceptions.
A better way to handle this exception is to either
pass it to the caller. i.e. don't catch it.
call Thread.currentThread().interrupt() so the interrupt is not lost.
If such an exception should be impossible, wrap it in a throw new AssertionError(ex)
That is used in situations where an exception may occur but the response to the exception is the same as normal continuation from the try block. A common example is calling sleep(). (However, that's actually often a bad example because being interrupted often signals that an operation should be abandoned.)
InterruptedException is what's called a checked exception. When added to a method you want to call, it's a way of signifying that you must account for this situation, namely that the time you need to process the results of the call may be pre-empted by another thread in the system.
Assume for the moment that you have 6-7 statements in a try block, and you assume they will run in a more or less atomic fashion. Among those statements is one that relies on thread-aware behavior. If that call is pre-empted, your subsequent statements won't run, and you'll have to handle the consequences.
People have all sorts of reasons for catching this exception but taking no action. I can't think of many good reasons for doing this, unless I can clearly show that being interrupted doesn't create an undesirable side-effect in my code. Given any example piece of code that shows this behavior, I would guess no catch logic was included because a) the programmer had no plan for dealing with it; b) the programmer merely wanted to step past the check so the code compiles.
On a recent project I recommended catching a RuntimeException within a test harness code and logging it. The code processes a series of inputs from a database, and I do not want the test to stop due to failure of any one input (Null values, Illegal arguments, etc.). Needless to say, my suggestion triggered a passionate discussion.
Is catching any kind of RuntimeException acceptable? If yes, what are other scenarios where it is OK to catch RuntimeExceptions?
You catch RuntimeException for the same reason that you catch any exception: You plan to do something with it. Perhaps you can correct whatever caused the exception. Perhaps you simply want to re-throw with a different exception type.
Catching and ignoring any exception, however, is extremely bad practice.
Unless you can correct a RuntimeException, you don't want to catch it...
...only true from a developers point of view....
you have to catch all exceptions before they reach up to the UI and make your user sad. This means on the "highest level" you want to catch anything that happend further down. Then you can let the user know there was a problem and at the same time take measures to inform the developers, like sending out alarm mails or whatever...
It is basically considered a data/programming error that could not be forseen, thus you want to improve future releases of the software while at the same time take the user by the hand and move on in a controlled manner...
RuntimeException is intended to be used for programmer errors. As such it should never be caught. There are a few cases where it should be:
you are calling code that comes from a 3rd party where you do not have control over when they throw exception. I would argue that you should do this on a case by case basis and wrap the usage of the 3rd party code within your own classes so you can pass back non-runtime exceptions.
your program cannot crash and leave a stack trace for the user to see. In this case it should go around main and around any threads and event handling code. The program should probably exit when such exception occurs as well.
In your specific case I would have to question why you are having RuntimeExceptions occur in the tests - you should be fixing them instead of working around them.
So you should guarantee that your code only throws RuntimeExceptions when you want to have the program exit. You should only catch RuntimeExceptions when you want to log it and exit. That is what is in line with the intent of RuntimeExceptions.
You can look at this discussion for some other reasons that people give... I personally haven't found a compelling reason in the answers though.
In my code 99% of my exceptions are derived from runtime_exception.
The reasons I catch exceptions are:
Catch Log and Fix problem.
Catch Log and Generate a more specific exception and throw
Catch Log and rethrow.
Catch Log and Kill operation (discard exception)
User/request initiated action fails.
An HTTP request handler for example. I would rather the requested operation die rather than bring the Service down. (Though preferably the handler has enough sense to return a 500 error code.)
Test case passed/failed with an exception.
All exceptions not in the main thread.
Allowing exceptions to escape a thread is usually badly documented but usually causes program termination (without stack unwinding).
Years ago, we wrote a control system framework and the Agent objects caught runtime exceptions, logged them if they could and continued.
Yes we caught Runtime exceptions including OutOfMemory in our framework code( and forced a GC, and it's surprising how well that kept even quite leaky code running.)
We had code that was doing very mathematical things involving the real world; and from time to time a Not-A-Number would get in due to tiny rounding errors and it coped okay with that too.
So in framework / "must not exit" code I think it can be justifiable. And when it works it's pretty cool.
The code was pretty solid, but it ran hardware, and hardware tends to give screwy answers sometimes.
It was designed to run without human intervention for months at a time.
It worked extremely well in our tests.
As part of the error recovery code, it could resort to rebooting the entire building using the UPS's ability to turn off in N minutes and turn on in M minutes.
Sometimes hardware faults need to power cycled :)
If I remember, the last resort after an unsuccessful power cycle was it sending an email to it's owners, saying
"I tried to fix myself and I can't; the problem is in subsystem XYZ", and included a link to raise a support call back to us.
Sadly the project got canned before it could become self aware :)>
Personally, I've always been told that you want to catch all RuntimeExceptions; however, you also want to do something about the exception, such as running a failsafe or possibly just informing the user that an error occurred.
The last Java project that I worked on had a similar approach, at the very least, we would log the exception so that if a user called complaining about a bug, we could find out exactly what happened and see where the error occurred.
Edit 1: As kdgregory said, catching and ignoring are two different things, generally, people are opposed to the latter :-)
We all know that checked exceptions and RuntimeExceptions are the two categories of exceptions. It is always suggested that we handle (either try-catch or throw) the checked exceptions because they are the programming conditions where unfortunately programmer can not to do anything on its own;
Like FileNotFoundException it is not the programmer who puts files on user's drive if program is actually trying to read the file 1.txt which is supposed to be there on f:\ of user with the statements:
File f11 = new File("f:\\1.txt");
FileInputStream fos = new FileInputStream(f11);
If the file is found it's all ok, but what happens in the other case if the file is not found is that, program crashes down with 0 error from the user. In this scenario programmer did not do anything wrong. This could be a checked exception which must be caught for the program to continue running.
Let me also explain the second scenario with which the concept of RuntimeException will be clear. Consider following code:
int a = {1,2,3,4,5};
System.out.println(a[9]);
This is poor coding which generates the ArrayIndexOutOfBoundsException. Which is an example of RuntimeException. So programmer should not actually handle the exception, let it crash the program, and later fix the logic.
You catch RuntimeException when you want to process it. Maybe you want to rethrow it as a different exception or log it to a file or database, or you want to turn on some exception flag in the return type, etc.
You catch RuntimeExceptions (in any language: unexpected exceptions/“all” exceptions) when your program is doing multiple subtasks and it makes sense to complete every one you can rather than stopping on the first unexpected situation. A test suite is a fine situation to do this — you want to know which of all the tests failed, not just the first test. The key characteristic is that each test is independent of all the others — it doesn't matter whether a previous test doesn't run because the order is not significant anyway.
Another common situation is a server; you don’t want to shut down just because one request was malformed in a way you didn't expect. (Unless it’s really, really important to minimize the chances of inconsistent state.)
In any of these situations, the appropriate thing to do is log/report the exception and continue with the remaining tasks.
One could vaguely generalize to any exception: it is “appropriate to catch” an exception if and only if there is something sensible to do after catching it: how your program should continue.
If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.
Here's the bottom line guideline.
From Java Docs. Please read this Unchecked Exceptions — The Controversy
In what situations should one catch java.lang.Error on an application?
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.
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
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.
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.
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.
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.
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.
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.
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.
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).
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.
it's quite handy to catch java.lang.AssertionError in a test environment...
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.
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.
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
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.