Printing exceptions thrown by thread-pool threads, Java's default behavior - java

I asked this question: Printing the stack trace from a newly created thread when an unchecked exception is thrown in Eclipse
And got this in a reply by the user Gray: "By default there is nothing that prints the exceptions thrown by thread-pool threads."
I'd like to know the reason why that is. It seems confusing to me to have a thread-pool thread throw an unchecked exception and stop working without printing any errors by default.

One would have to alter the program, for instance a Thread has a set(Default)UncaughtExceptionHandler.
With AOP one could achieve such a thing.

Because if it printed it, another developer would ask why it cripples the output of the program with unwanted stack traces, and reduces the throughput drastically by writing the stack traces to a synchronized PrintStream. If you want the exceptions to be printed, then print them by yourself. Nothing prevents you from doing it.
The answer you got shows how to do that. You could also wrap all your runnables with another runnable that catches the runtime exceptions, prints them when they are thrown, and rethrow them.

Related

Is it possible to handle all Errors in Java?

I know that Error is Throwable (so it can be handled) and Error handling isn't best practice but suppose we have a requirement to catch all Error.
It is possible in general? I mean what about Errors which can appear in daemon threads? They will crash jvm and I won't know about it.
And can I miss Error even if I surround main(String... args) with try-catch?
You can catch the uncaught exceptions via Thread.setUncaughtExceptionHandler()
Set the default handler invoked when a thread abruptly terminates due
to an uncaught exception, and no other handler has been defined for
that thread.
Uncaught exception handling is controlled first by the thread, then by
the thread's ThreadGroup object and finally by the default uncaught
exception handler. If the thread does not have an explicit uncaught
exception handler set, and the thread's thread group (including parent
thread groups) does not specialize its uncaughtException method, then
the default handler's uncaughtException method will be invoked.
Whether that's a good idea is another question (!). It may be that you simply want to clear up resources, shut down connections etc., log the issue and/or alert the user. If you do have critical issues like OutOfMemoryErrors then there's little else you can do.
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.
Now, since Error does indeed extends Throwable, it is possible to catch 'any' error via a simple try-catch statement as follows:
try{
//Error causing code here...
}catch(Error e){
//Handle error here...
}
However, since errors come in different forms, a thrown error may or may not be accompanied by a change in the jvm's behaviour to cause unexpected results.
Consider the Error OutOfMemoryError. When this Error is thrown, the JVM's heap may be so full that any type of handling code results in another OutOfMemoryError being thrown, voiding any attempt of recovery.
Furthermore, even when running on the "primary" thread (the one the application starts in), a error could cause a JVM to crash before every throwing a Error.
Looking at the description of VirtualMachineError (of which Errors such as OutOfMemoryError, StackOverflowError, InternalError, etc are subclasses of) we see:
Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating.
The javadoc itself states that the jvm no longer can continue operation normally much less allow a programmer to just 'handle' them away.
On the other hand, errors such as UnsatisfiedLinkError generally do not cause a problem with the jvm straight away and can generally be handled (whether this is good practice is debatable). I personally have once used a structure that involves handling a UnsatisfiedLinkError to determine the correct library to load for JNI.
Now, can all errors be handled? Theoretically yes, if we assume that the JVM can continue operation perfectly despite claiming to have failed fatally... With that in regard, practically only a small subset of errors are handleable. Whether or not these small subset of errors should be handled is also a highly controversial topic.
You can handle exceptions, but you can't handle errors.

Custom exception. Where to log it

I created a CustomExceptionClass that its messages are from a configuration file and are a friendlier message to the user.
Then I want to log wich exception was thrown because, if something went wrong, I want to know details then I can fix this. So, I have a doubt.
Where to log these exceptions using log4j? Inside the CustomExceptionClass, or I let the method that throws this exception log it?
You should log wherever you are catching the Exception. If you are not catching it anywhere it really depends how you are running your application.
I'm not sure if you have a question about log4j in particular, but that API simply requires something to call log.error(Object,Throwable), passing in the message as the first parameter and the error as the second parameter. (log is of course a Log4J logger reference.)
Regarding the question of where to call log.error, do not call log.error from within your CustomExceptionClass subclass of Throwable. Instead, I'd make the decision as follows:
If you want to log details about exactly what happened, but you don't plan to put those details into your subclass of Exception, then log the details before throwing the error.
Similarly, if you want to log something specific regardless of whether or how the Exception is caught, then obviously you need to do this before throwing the Exception. You have relatively little control over who calls a non-private method.
Otherwise log in the catch block. This allows you to track both what happened and how your application responded as a result. If you just have the first piece of information, then other people will have to read the code in order to understand "so what?"
Finally, it's considered to be good practice to use uncaught exception handlers for all threads. See Thread.UncaughtExceptionHandler for more details. Basically you really want to at least log all Exceptions in long-running applications.
You should log it in the error handling code, not where the error is initially created.
I typically overload ToString and/or GetMessage in custom exceptions and simply log them per normal.

Why is exception.printStackTrace() considered bad practice?

There is a lot of material out there which suggests that printing the stack trace of an exception is bad practice.
E.g. from the RegexpSingleline check in Checkstyle:
This check can be used [...] to find common bad practice such as calling ex.printStacktrace()
However, I'm struggling to find anywhere which gives a valid reason why since surely the stack trace is very useful in tracking down what caused the exception. Things that I am aware of:
A stack trace should never be visible to end users (for user experience and security purposes)
Generating a stack trace is a relatively expensive process (though unlikely to be an issue in most 'exceptional' circumstances)
Many logging frameworks will print the stack trace for you (ours does not and no, we can't change it easily)
Printing the stack trace does not constitute error handling. It should be combined with other information logging and exception handling.
What other reasons are there for avoiding printing a stack trace in your code?
Throwable.printStackTrace() writes the stack trace to System.err PrintStream. The System.err stream and the underlying standard "error" output stream of the JVM process can be redirected by
invoking System.setErr() which changes the destination pointed to by System.err.
or by redirecting the process' error output stream. The error output stream may be redirected to a file/device
whose contents may be ignored by personnel,
the file/device may not be capable of log rotation, inferring that a process restart is required to close the open file/device handle, before archiving the existing contents of the file/device.
or the file/device actually discards all data written to it, as is the case of /dev/null.
Inferring from the above, invoking Throwable.printStackTrace() constitutes valid (not good/great) exception handling behavior, only
if you do not have System.err being reassigned throughout the duration of the application's lifetime,
and if you do not require log rotation while the application is running,
and if accepted/designed logging practice of the application is to write to System.err (and the JVM's standard error output stream).
In most cases, the above conditions are not satisfied. One may not be aware of other code running in the JVM, and one cannot predict the size of the log file or the runtime duration of the process, and a well designed logging practice would revolve around writing "machine-parseable" log files (a preferable but optional feature in a logger) in a known destination, to aid in support.
Finally, one ought to remember that the output of Throwable.printStackTrace() would definitely get interleaved with other content written to System.err (and possibly even System.out if both are redirected to the same file/device). This is an annoyance (for single-threaded apps) that one must deal with, for the data around exceptions is not easily parseable in such an event. Worse, it is highly likely that a multi-threaded application will produce very confusing logs as Throwable.printStackTrace() is not thread-safe.
There is no synchronization mechanism to synchronize the writing of the stack trace to System.err when multiple threads invoke Throwable.printStackTrace() at the same time. Resolving this actually requires your code to synchronize on the monitor associated with System.err (and also System.out, if the destination file/device is the same), and that is rather heavy price to pay for log file sanity. To take an example, the ConsoleHandler and StreamHandler classes are responsible for appending log records to console, in the logging facility provided by java.util.logging; the actual operation of publishing log records is synchronized - every thread that attempts to publish a log record must also acquire the lock on the monitor associated with the StreamHandler instance. If you wish to have the same guarantee of having non-interleaved log records using System.out/System.err, you must ensure the same - the messages are published to these streams in a serializable manner.
Considering all of the above, and the very restricted scenarios in which Throwable.printStackTrace() is actually useful, it often turns out that invoking it is a bad practice.
Extending the argument in the one of the previous paragraphs, it is also a poor choice to use Throwable.printStackTrace in conjunction with a logger that writes to the console. This is in part, due to the reason that the logger would synchronize on a different monitor, while your application would (possibly, if you don't want interleaved log records) synchronize on a different monitor. The argument also holds good when you use two different loggers that write to the same destination, in your application.
You are touching multiple issues here:
1) A stack trace should never be visibile to end users (for user experience and security purposes)
Yes, it should be accessible to diagnose problems of end-users, but end-user should not see them for two reasons:
They are very obscure and unreadable, the application will look very user-unfriendly.
Showing a stack trace to end-user might introduce a potential security risk. Correct me if I'm wrong, PHP actually prints function parameters in stack trace - brilliant, but very dangerous - if you would you get exception while connecting to the database, what are you likely to in the stacktrace?
2) Generating a stack trace is a relatively expensive process (though unlikely to be an issue in most 'exception'al circumstances)
Generating a stack trace happens when the exception is being created/thrown (that's why throwing an exception comes with a price), printing is not that expensive. In fact you can override Throwable#fillInStackTrace() in your custom exception effectively making throwing an exception almost as cheap as a simple GOTO statement.
3) Many logging frameworks will print the stack trace for you (ours does not and no, we can't change it easily)
Very good point. The main issue here is: if the framework logs the exception for you, do nothing (but make sure it does!) If you want to log the exception yourself, use logging framework like Logback or Log4J, to not put them on the raw console because it is very hard to control it.
With logging framework you can easily redirect stack traces to file, console or even send them to a specified e-mail address. With hardcoded printStackTrace() you have to live with the sysout.
4) Printing the stack trace does not constitute error handling. It should be combined with other information logging and exception handling.
Again: log SQLException correctly (with the full stack trace, using logging framework) and show nice: "Sorry, we are currently not able to process your request" message. Do you really think the user is interested in the reasons? Have you seen StackOverflow error screen? It's very humorous, but does not reveal any details. However it ensures the user that the problem will be investigated.
But he will call you immediately and you need to be able to diagnose the problem. So you need both: proper exception logging and user-friendly messages.
To wrap things up: always log exceptions (preferably using logging framework), but do not expose them to the end-user. Think carefully and about error-messages in your GUI, show stack traces only in development mode.
First thing printStackTrace() is not expensive as you state, because the stack trace is filled when the exception is created itself.
The idea is to pass anything that goes to logs through a logger framework, so that the logging can be controlled. Hence instead of using printStackTrace, just use something like Logger.log(msg, exception);
Printing the exception's stack trace in itself doesn't constitute bad practice, but only printing the stace trace when an exception occurs is probably the issue here -- often times, just printing a stack trace is not enough.
Also, there's a tendency to suspect that proper exception handling is not being performed if all that is being performed in a catch block is a e.printStackTrace. Improper handling could mean at best an problem is being ignored, and at worst a program that continues executing in an undefined or unexpected state.
Example
Let's consider the following example:
try {
initializeState();
} catch (TheSkyIsFallingEndOfTheWorldException e) {
e.printStackTrace();
}
continueProcessingAssumingThatTheStateIsCorrect();
Here, we want to do some initialization processing before we continue on to some processing that requires that the initialization had taken place.
In the above code, the exception should have been caught and properly handled to prevent the program from proceeding to the continueProcessingAssumingThatTheStateIsCorrect method which we could assume would cause problems.
In many instances, e.printStackTrace() is an indication that some exception is being swallowed and processing is allowed to proceed as if no problem every occurred.
Why has this become a problem?
Probably one of the biggest reason that poor exception handling has become more prevalent is due to how IDEs such as Eclipse will auto-generate code that will perform a e.printStackTrace for the exception handling:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
(The above is an actual try-catch auto-generated by Eclipse to handle an InterruptedException thrown by Thread.sleep.)
For most applications, just printing the stack trace to standard error is probably not going to be sufficient. Improper exception handling could in many instances lead to an application running in a state that is unexpected and could be leading to unexpected and undefined behavior.
I think your list of reasons is a pretty comprehensive one.
One particularly bad example that I've encountered more than once goes like this:
try {
// do stuff
} catch (Exception e) {
e.printStackTrace(); // and swallow the exception
}
The problem with the above code is that the handling consists entirely of the printStackTrace call: the exception isn't really handled properly nor is it allowed to escape.
On the other hand, as a rule I always log the stack trace whenever there's an unexpected exception in my code. Over the years this policy has saved me a lot of debugging time.
Finally, on a lighter note, God's Perfect Exception.
printStackTrace() prints to a console. In production settings, nobody is ever watching at that. Suraj is correct, should pass this information to a logger.
It is not bad practice because something is 'wrong' about PrintStackTrace(), but because it's 'code smell'.
Most of the time the PrintStackTrace() call is there because somebody failed to properly handle the exception. Once you deal with the exception in a proper way you generally don't care about the StackTrace any more.
Additionally, displaying the stacktrace on stderr is generally only useful when debugging, not in production because very often stderr goes nowhere. Logging it makes more sense. But just replacing PrintStackTrace() with logging the exception still leaves you with an application which failed but keeps running like nothing happened.
In server applications the stacktrace blows up your stdout/stderr file. It may become larger and larger and is filled with useless data because usually you have no context and no timestamp and so on.
e.g. catalina.out when using tomcat as container
As some guys already mentioned here the problem is with the exception swallowing in case you just call e.printStackTrace() in the catch block. It won't stop the thread execution and will continue after the try block as in normal condition.
Instead of that you need either try to recover from the exception (in case it is recoverable), or to throw RuntimeException, or to bubble the exception to the caller in order to avoid silent crashes (for example, due to improper logger configuration).

Global Exception Handlers in Java

I am thinking of setting up a global, default Exception handler for my (Android) Mobile application(which uses Java syntax) using Thread.setDefaultUncaughtExceptionHandler(...) call. I am thinking of just displaying an Alert Dialog with appropriate message to the user.
Are there any gotchas, caveats and rules that one needs to follow when setting DefaultExceptionHandlers? Any best practices like making sure that the process is killed, full stack trace is written to logs etc. ?
Links to documentation, tutorials etc. that can throw some light on this are welcome.
Thanks.
The name is a bit misleading, because using that method will set a default exception handler for all threads.
Make sure no exceptions can be thrown from your exception handler.
If you're doing GUI stuff from your exception handler, make sure you're doing it from the right thread.
An uncaught exception will only stop the thread where the exception took place, if that also causes the process to terminate depends on any other threads that might be running.
One possible problem with creating a global exception handler is you may get stuck in a loop of exceptions - some exceptions will be thrown repeatedly unless a program is terminated.
If you mean that when an exception is thrown, a message is displayed then the app is terminated, then you'll be fine.

IllegalMonitorStateException

When running our program we get an exception of type java.lang.IllegalMonitorStateException. On Java6 API website, it says there is a constructor that gives a details about the exception: IllegalMonitorStateException(String s)
How can we use this to get a better idea of where the bug is in our code? Is there anything else we can do (besides lots of debugging which we're currently doing) to pinpoint the function or line that failed?
The details must be given when the Exception is created (Constructor, right?) and if you are not creating it, there is no way for you to provide the details.
You can analize the StackTrace of the Exception. It shows the classes, methods and souce line which were called to cause the Exception.
One cause for the IllegalMonitorStateException is trying to wait on an Object without having synchronized on it. See the Javadoc.
There are other possible causes and the Exception may be thrown by some library/external code. I think only the StackTrace can help...
This is maybe occurring because the instance of the object which you are calling wait or notify on is different that the instance you synchronized with. For example:
Integer a;
a = new Integer(0);
synchronized(a) {
System.out.printf("I synchronized on %h.", a);
++a;
System.out.printf("But, I am calling notify for %h and I hold no lock for it.", a);
a.notify();
}
This will throw the IllegalMonitorStateException because the instance that 'a' points to is no longer the same.
How can we use this to get a better
idea of where the bug is in our code?
Is there anything else we can do
(besides lots of debugging which we're
currently doing) to pinpoint the
function or line that failed?
In this case, printing the message by itself probably won't help much. What you need is a stacktrace with source file names and line numbers.
Make sure that all relevant ".class" files / JARs were built with file and line number debug information included. This is the default, but compiling with "-g:none" will strip this ... as will most JAR file obfuscators.
Next, add a try / catch block to catch the IllegalMonitorStateException and either call ex.printStackTrace() or log the exception.
From the stacktrace you should be able to see what line in the code threw the exception. The chances are that is was a call to Object.wait(...) or something like that. Check the javadoc for the offending method to find out what circumstances cause the exception to be thrown.
(And once you are done, remember to move the try / catch block you added.)
You should print the stack trace, which will give you the exact location in the source.
Unfortunately it's not uncommon for the JVM to throw exceptions which contain no detail message to assist in debugging.

Categories

Resources