Related
Disclaimer : I'm coming from C# world so this is question might be biased by my previous experience
I have a method that is initializing logging. If this fails, the rest of the app should not run as any call to logger will throw a NullPointerException.
Today, my code is catching the exception and printing an error log via System.err. To me, this is a mistake, it should let the exception propagate up until it kills the app.
So I started removing the try catch and I suddenly got complains from the compiler saying that I should declare my exception on the whole stack where this method is called.
I understand the logic behind it and used to found it practical : you know how this method is capable of failing.
However, that doesn't sound right to me in term of separation of responsibility. I don't want the upper layers to be aware of this potential IOException fail, it is a very specialized behavior that shouldn't be known to , for example, the main method.
And, if we push this logic, it means that :
the highest layer will eventually have to declare the whole scope of exceptions (From IO to Network to custom exceptions...)
Any addition of a new exception can potentially impact a lot of files and code
Am I missing something or this is intended exception design ?
I think what you are looking for is not a Java Exception, it is a Java Error.
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. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
https://docs.oracle.com/javase/7/docs/api/java/lang/Error.html
You can throw a error, which indicates that your app won't work anymore, which you declared as correct behaviour.
You can encapsulate your checked exception in a RuntimeException (or one if its children), which does not force you to declare the exception:
public X execute() {
try {
return someThrowingMethod();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
If you can't initialize the logger and this is an enterprise application, I recommend killing your application with an exit code that explains the reason. If this is a client application, I recommend showing a message to the client stating the problem, recommending to the client that you report this back to you, and allowing them the choice of whether to proceed or not
Surprisingly google didn't describe any catastrophic scenarios my twisted mind craved for.
Anywhere I read, catching errors is discouraged. Basic rule seems to be that if your application produced error, it's already dead, beyond saving. So if you catch errors in your main function, does your program turn into zombie?
How can even error be caught if the program is already collapsing? Can catching errors do something real bad? Which errors are worst and which are sometimes caught? Could you describe a little test case that can produce the errors (like really produce them, not just throw them) so that I can see that they do if I catch them and ignore them?
Not much happens except that the thrown object is caught. Your process can be in a bad place, though, depending on what caused the error.
A StackOverflowError is pretty undramatic to catch - it's thrown when the maximum stack depth is exceeded, and since it then starts popping the call stack, it's no longer a problem (unless you try calling the offending method again).
class SO {
static int stackOverflow(){ return stackOverflow(); }
public static void main(String... args) {
try {
stackOverflow();
} catch (StackOverflowError e) {
System.out.println("Oh well, life goes on.");
}
}
}
Other errors, like OutOfMemoryError, are somewhat more problematic - there will still be too much memory used after it's been thrown. Some are directly fatal, like ClassFormatError, which means that you're trying to load a broken class file (and it's usually thrown in places where you can't catch it).
Other Errors are somewhere inbetween. AssertionError, for example, is thrown when a programmer-defined condition (like assert answer == 42;) isn't met, but only if you've enabled assertions.
Long story short, though: If you're catching specific errors, you're probably doing the wrong thing (unless you really know what you're doing!). If you're running a server app and want it to keep running, you're probably better of letting the current thread or process die and have it restarted by some kind of monitor.
Catching an Exception or Error is not a good idea, unless;
you can do something useful with it.
as a last resort to ensure it is logged correctly or in a submitted Runnable to an ExecutorService. In this case catching Throwable may be desirable.
Nothing terrible will happen if you catch an Error, however you can't pretend it didn't happen either (i.e. you can't just continue as if it didn't matter)
Note: not catching an error can be a bad thing for multi-threaded applications. This is because an uncaught error only closes the current thread. If there are multiple threads, they will keep running if at least one is not a daemon This can leave a program running but in a bad state.
I ask what happens.
Nothing special, you catch it and you can deal with it or log it.
Are you talking about catching Exceptions? There are two types of Exceptions checked and unchecked. The reason to catch an Exception as simple as catching a programmer defined Exception which enables the user to reenter the data. This normally applies to checked Exceptions.
Unchecked Exceptions cannot be recovered from and you might ask why catch them at all? Perhaps the developer wants to catch it to log the conditions which caused the Exception and to better troubleshoot the issue.
Here is an article discussing them both.
http://tutorials.jenkov.com/java-exception-handling/checked-or-unchecked-exceptions.html
We have a piece of code for reading from queue
while(true){
try {
message = readMessageFromQueue();
processMesage(message); //Writes into DB and some other operation
}catch(Exception e) {
log the exception
}
}
Now there are ten threads which are spawned using executor service with the aim of running forever. However we have noticed after sometime we deploy(it can be 10-15 days or month) the number of thread is getting reduced(Write per second is also decreasing because of that).
The question is should we catch Error or only exception in the code which we want to run forever like this and is catching Exception can cause this problem ?
Yes, it's better to catch a Throwable there, not just Exception. Depending on your processing you might get, for example, a StackOverflowError that will kill your thread without logging. You might not be able to recover from it, but at least you can debug the problem latter.
From what I understand, you're asking if it is okay to catch by general Exception versus specific exceptions, like ArrayOutOfBoundsException. So, I guess my answer come down to whatever you prefer. You can catch by Exception, which isn't usually advised because you should always know what your code is doing and thus what could go wrong, but it does accomplish your tasks. Now, the reason you should catch by specific exceptions is that you can have different methods of handling different errors. Maybe the way you are handling the error isn't universally applicable to all errors, so when the thread sees an exception it isn't designed to expect, it crashes leaving you with one less thread.
I prefer catching specific exceptions of I can do something gracefully with that failure (like retry or do some default behavior). But if an exception means the program can't continue at all regardless, than catching the most generic exception and terminating is fine.
catching Exception is a "shotgun" approach to exception handling - "Whatever exception you will throw, I will catch it!".
catching a specific, ideally custom Exception is preferred mainly because you know where that exception is thrown, and you can gracefully handle that exception, or do some methods specifically for a certain exception. Therefore gives you more control of your application.
hope this helps.
Is the following way to code good practice?
try {
//my code here
} catch (Exception e) {
logger.error("Some error ", e);
throw new MyCustomException("Some error ", e);
}
Moreover, should I..
use only the logger?
throw only the exception?
do both?
I understand that with throw I can catch the exception in another part of the callstack, but maybe additional logging has some hidden benefits and is useful as well.
Normally, I'd argue that you should either log or rethrow. Doing both will just cause every layer to log the exception again and again, which makes the logs hard to read. Even worse, it's hard to figure out how many errors you actually have - was it seven errors, or seven layers of the app which logged the same error?
This means that if you suppress an exception, you log it and say why you didn't think it was worth rethrowing.
On the other hand, if you re-throw the exception, you know it's either going to be caught and suppressed (in which case the catcher logs the exception and why it was suppressed), or it will bubble up out of your app and be caught by the app container, which will catch and log the exception. Every exception shows up once and only once in the logs.
I use both in some cases, logging and throwing the exception. Especially, it's useful in APIs. By throwing the exception, we allow the caller to handle it, and by logging, we can identify the root cause of it ourselves.
And, if the caller is in the same system, then if we add logs in every catch, there will be duplicate logs.
When using the pattern you suggest, you usually end up with error events being reported multiple times in the log. In addition, it's not always simple to connect between them when reading the log.
Personally I prefer logging error events only once, and doing it in the higher call levels. Therefore I almost never log & re-throw. I usually let the exception go up the call stack until it reached a context where it can be handled somehow, and this is where I log.
If the exceptions are wrapped and re-thrown correctly, the context should be perfectly clear from the stack traces of the single log message.
The proper answer would be: "it depends"
You do want in general log the exceptions that you catch, since they correspond to something going wrong. That is why code analysis tools such as sonar will raise warnings when you do not log them.
Consider the following taks: parsing a file. While parsing the file you actually try to parse each line. Sometimes some lines will be malformed, and therefore you don't want to stop parsing the file because of it. In that case, you probably want to just log the wrong line and keep going on the file.
However, imagine that at some point you encounter an I/O exception while reading (for example some other program deleted the file while yours was accessing it).
In this case, you will probably want to log your log the error you encounter, and throw a new exception to stop processing the whole file.
So in short, you have to think about what is the best thing to do. But both practices are not bad.
I think you may need to use the pattern judiciously. As you've written the above, for each exception you're going to log 2 stacktraces and that may fill your logs with excessive information.
With respect to logging vs. throwing, they're two separate concerns. Throwing an exception will interrupt your execution, prevent any further work, perhaps rollback database commits etc. Logging will simply dump info to the log file (or elsewhere). It's of more use for debugging, and often much more difficult to test.
I know that is really old question, but I have an another solution.
Consider this. You can log the problem in catch block and throw a new unchecked exception (of course with passing the previous one inside). In such solution there is no overflow in the logs and exception still bubble up to the highest level.
try {
//my code here
} catch (SomeException e) {
logger.error("Some error occured", e);
throw new MyUncheckedException("Some error ", e);
}
My opinion.
When you need to throw an exception, no matter if it is a Checked or UnChecked(Most RD would not catch this.). It means that you want to do something else by stopping the process.
When you need to log something.
It means you want to track it.
It's quite different things.
You need to check what you really need.
BTW: If your exception was thrown by getting no data from DB.
I suggest you to modify the process to return an empty Data Object(POJO). It is better than throwing an exception.
We recently had a problem with a Java server application where the application was throwing Errors which were not caught because Error is a separate subclass of Throwable and we were only catching Exceptions.
We solved the immediate problem by catching Throwables rather than Exceptions, but this got me thinking as to why you would ever want to catch Exceptions, rather than Throwables, because you would then miss the Errors.
So, why would you want to catch Exceptions, when you can catch Throwables?
From the Java API documentation:
The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch.
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
Errors usually are low-level (eg., raised by the virtual machine) and should not be caught by the application since reasonable continuation might not be possible.
It all depends a bit on what you're going to do with an Error once you've caught it. In general, catching Errors probably shouldn't be seen as part of your "normal" exception flow. If you do catch one, you shouldn't be thinking about "carrying on as though nothing has happened", because the JVM (and various libraries) will use Errors as a way of signalling that "something really serious has happened and we need to shut down as soon as possible". In general, it's best to listen to them when they're telling you the end is nigh.
Another issue is that the recoverability or not from an Error may depend on the particular virtual machine, which is something you may or not have control over.
That said, there are a few corner cases where it is safe and/or desirable to catch Errors, or at least certain subclasses:
There are cases where you really do want to stop the normal course of flow: e.g. if you're in a Servlet, you might not want the Servlet runner's default exception handler to announce to the world that you've had an OutOfMemoryError, whether or not you can recover from it.
Occasionally, an Error will be thrown in cases where the JVM can cleanly recover from the cause of the error. For example, if an OutOfMemoryError occurs while attempting to allocate an array, in Hotspot at least, it seems you can safely recover from this. (There are of course other cases where an OutOfMemoryError could be thrown where it isn't safe to try and plough on.)
So the bottom line is: if you do catch Throwable/Error rather than Exception, it should be a well-defined case where you know you're "doing something special".
Edit: Possibly this is obvious, but I forgot to say that in practice, the JVM might not actually invoke your catch clause on an Error. I've definitely seen Hotspot glibly gloss over attempts to catch certain OutOfMemoryErrors and NoClassDefFoundError.
A lot of the other answers are looking at things too narrowly.
As they say, if you are writing application code, you should not catch Throwable. You can't do anything about it, so allowing the surrounding system (JVM or framework) to handle these issues is best.
However, if you are writing "system code", like a framework or other low-level code then you may very well want to catch Throwable. The reason is to attempt to report the exception, perhaps in a log file. In some cases your logging will fail, but in most cases it will succeed and you will have the information you need to resolve the issue. Once you have made your logging attempt you should then either rethrow, kill the current thread, or exit the entire JVM.
Usually Errors are problems you cannot possibly recover from, like OutOfMemoryError. There's nothing to do by catching them, so you should usually let them escape, and bring down the virtual machine.
I'll go a slightly different route from others.
There are many cases where you would want to catch Throwable (mainly to log/report that something evil happened).
However, you need to be careful and rethrow anything that you cannot deal with.
This is especially true of ThreadDeath.
If you ever catch Throwable, be sure to do the following:
try {
...
} catch (SomeExceptionYouCanDoSomethingWith e) {
// handle it
} catch (ThreadDeath t) {
throw t;
} catch (Throwable t) {
// log & rethrow
}
There's at least one case when I think you may have to catch a throwable or a generic exception - if you're running a separate thread to perform a task, you may want to know if the "run" method of the thread has catched some exception or not. In that case, you probably will do something like this:
public void run() {
try {
...
}
catch(Throwable t) {
threadCompletionError = t;
}
}
I am really not sure if it's the best approach, but it works. And I was having a "ClassNotFound" error being raised by the JVM, and it's an error and not an exception. If I let the exception be thrown, I am not sure how to catch it in the calling thread (probably there's a method but I don't know about it - yet).
As for the ThreadDeath method, don't call the "Thread.stop()" method. Call Thread.interrupt and have your thread to check if it was interrupted by someone.
This post won't make the "checked exceptions are bad" people happy. However, what I am basing my answer on is how Java exceptions are intended to be used as defined by the people that created the language.
Quick reference chart:
Throwable - never catch this
Error - indicates a VM error - never catch this
RuntimeException - indicated a programmer error - never catch this
Exception - never catch this
The reason you should not catch Exception is that it catches all of the subclasses, including RuntimeException.
The reason you should not catch Throwable is that it catches all of the subclasses, including Error and Exception.
There are exceptions (no pun intended) to the above "rules":
Code you are working with (from a 3rd party) throws Throwable or Exception
You are running untrusted code that could cause your program to crash if it thew an exception.
For the second one usually it is enough to wrap main, event handling code, and threads with the catch to Throwable and then check the actual type of the exception and deal with it as appropriate.
Do NOT ever catch Throwable or Error and you should generally not simply catch a generic Exception either. Errors are generally things that most reasonable programs cannot possibly recover from. If you know what is going on, you might be able to recover from one specific error, but in that case, you should catch only that one particular error and not all errors in general.
A good reason not to catch Error is because of ThreadDeath. ThreadDeath is a fairly normal occurrence that can theoretically be thrown from anywhere (other processes like the JVM itself can generate it), and the whole point of it is to kill your thread. ThreadDeath is explicitly an Error rather than an Exception because too many people catch all Exceptions. If you ever were to catch ThreadDeath, you must rethrow it so that your thread actually dies.
If you have control over the source, it should probably be restructured to throw an Exception rather than an Error. If you don't, you should probably call to the vendor and complain. Errors should be reserved for only things that are terminal with no possible way to recover from them.
Normally when programming, you should only catch a specific exception (such as IOException). In a lot of programs you can see a very toplevel
try {
...
} catch(Exception e) {
...
}
That catches all errors which could be recoverable and all those which indicate a bug in your code, e.g. InvalidArgumentException, NullPointerException. You can then automatically send an eMail, display a message box or whatever you like, since the JavaVM itself is still working fine.
Everything derived from Error is something very bad, you can't do anything against. The question is, if it makes sense to catch a OutOfMemoryError or a VirtualMachineError. (It is a error in the JavaVM itself, probably you can't even display a message box or send an eMail then)
You should probably not a class derived from Error, you should derive from Exception or RuntimeException.
I know it might be counter-intuitive, but just because you can catch all sorts of Exceptions and Throwables and Errors does not mean you should.
Over-aggressive catching of java.lang.Exception can lead to some serious bugs in applications - because unexpected Exceptions never bubble up, are never caught during development/testing, etc.
Best practice: only catch
Exceptions that you can handle
Exceptions that are necessary to catch
In general it would be reasonable to try to catch Errors if only so that can be properly reported.
However, I believe there are cases when it would be appropriate to catch an Error and not report it. I'm referring to UnsatisfiedLinkError. In JAI the library uses some native libraries to implement most of the operators for performance reasons, however if the library fails to load (doesnt exist, wrong format, unsupported platform) the library will still function because it will fall back into a java only mode.
Slightly off topic, but you may also want to look at this very good article about exceptions.
Why not catch them all? Then log them, at least you know you have an error. So better catch Throwable/s than Exception/s only.
There is no point in catching Error.
Errors are used to indicate something went really wrong in your application and it should be restarted.
For instance one common error is
java.lang.OutOfMemoryError
There is NOTHING you can do when that happens. Is already too late, the JVM has exhausted all its options to get more memory but it is impossible.
See this other answer to understand more about the three kinds of exceptions.