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?
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:
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.
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
You are touching multiple issues here:
Yes, it should be accessible to diagnose problems of end-users, but end-user should not see them for two reasons:
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.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 thesysout
.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.
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 ae.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:
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:(The above is an actual
try-catch
auto-generated by Eclipse to handle anInterruptedException
thrown byThread.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.
As some guys already mentioned here the problem is with the exception swallowing in case you just call
e.printStackTrace()
in thecatch
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).