What does the printStackTrace() method do?
printStackTrace() - a Throwable method that outputs full exception information (type, message, call stack) to System.err.
Junior Level
Definition
printStackTrace() - a Throwable method that outputs full exception information (type, message, call stack) to System.err.
Example
try {
int x = 10 / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
// Output: java.lang.ArithmeticException: / by zero
// at com.example.Main.main(Main.java:10)
}
What it shows
- Exception type:
java.lang.ArithmeticException - Message:
/ by zero - Call stack: in which file, method and line the error occurred
When to use
- Only for debugging and prototyping, when you need to quickly see the stack in console without setting up a logger
- Do not use in production code
WHY printStackTrace() is bad for production
printStackTrace() is “raw” output that:
- Writes to
System.err, not to your log file. In production, logs are collected centrally (ELK, Splunk), andSystem.errmay be redirected to/dev/nullor lost on container restart - Adds no context: no timestamp, trace ID, class name - just bare stack. Try finding the right error among thousands like it
- Splits stack into separate lines. In Kubernetes each line of
printStackTrace()becomes a separate JSON record in ElasticSearch - instead of one readable log you get 50 scattered ones - Blocks the thread -
System.erris synchronized. Under high load, 100 threads will queue for writing
When NOT to use printStackTrace()
- Production code - replace with logger (
log.error("msg", e)) - Multithreaded applications -
System.erris synchronized, creates contention - Web applications - stack in HTTP response exposes internal structure (Security)
- ELK/Splunk infrastructures -
printStackTrace()splits one stack into 50+ separate JSON records - Highload systems - blocking on
System.errwhen disk/pipe is full
Middle Level
Why it works slowly
1. Synchronization:
System.err is a PrintStream object. All its methods use synchronization. In a multithreaded application, 100 threads will wait for the lock.
2. Native stack conversion:
Throwable lazily converts native backtrace to StackTraceElement[] array exactly at the moment of stack access.
Output to string
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
Comparison with loggers
// BAD - synchronization, no context, splits logs
e.printStackTrace();
// GOOD - async, with context, JSON-friendly
log.error("Failed to process order id={}", id, e);
Loggers can:
- Format stack into one line or JSON
- Trim excessively long stacks
- Add JAR file and version information
- Write to file, not console
Where it actually writes
In Kubernetes/Docker, System.err is captured and written to JSON logs. But printStackTrace() outputs each line as a separate record.
Result: instead of one error log - 50+ scattered records in ElasticSearch.
Senior Level
Standard I/O blocking
If disk is full or console pipe is clogged, printStackTrace() will block the execution thread for an indefinite time.
Senior Rule: in production code, printStackTrace() should be blocked by static analysis rules (Checkstyle/Sonar).
Circular Causes
On circular dependency in cause (though initCause checks for this), printStackTrace has protection and prints [CIRCULAR REFERENCE], not going into infinite recursion.
Security
Stack trace in console exposes library versions and path structure. In web applications, never return printStackTrace() in HTTP response - use @ControllerAdvice.
Alternatives
// Programmatically get stack as string
String stackTrace = ExceptionUtils.getStackTrace(e); // Apache Commons
// Logger
log.error("Context message", e); // Logback/Log4j2
// Thread Dumps - if application is hung
// jstack <pid> or jcmd <pid> Thread.print
Diagnostics
jstack <pid>- state of all monitors and threadsjcmd <pid> Thread.print- jstack alternative- Static analysis - Sonar blocks
printStackTrace()in production code - JSON Layout - logs should be in JSON format for ELK/Splunk
Interview Cheat Sheet
Must know:
printStackTrace()outputs exception type, message and call stack toSystem.err- Do NOT use in production: writes to
System.err, not log file; no timestamp/trace ID; blocks thread (synchronized) - In Kubernetes/Docker each line of
printStackTrace()becomes a separate JSON record in ELK - one stack is split into 50+ records System.err-PrintStreamwith synchronization; under high load threads queue- In production replace with
log.error("context", e)- async, with context, JSON-friendly printStackTrace()protects against circular causes - prints[CIRCULAR REFERENCE]
Frequent follow-up questions:
- Why is printStackTrace() bad for production? - 4 reasons: writes to System.err (not log), no context, splits stack into lines, blocks thread
- How to get stack as string programmatically? -
StringWriter+PrintWriterorExceptionUtils.getStackTrace(e)from Apache Commons - What happens on disk full? -
printStackTrace()blocks thread indefinitely, sinceSystem.erris synchronized - How to avoid stack leakage in HTTP response in Spring? - Use
@ControllerAdvice, never returnprintStackTrace()to client
Red flags (NOT to say):
- “I use printStackTrace() in production - it works” - You lose logs, block threads, expose code structure
- “No difference between printStackTrace() and logger” - Logger adds context, formats, writes to the right place
- “Stack in HTTP response is normal practice” - Exposes library versions and path structure (security vulnerability)
Related topics:
- [[15. What is a stack trace]]
- [[17. How to properly log exceptions]]
- [[19. Why you should not swallow exceptions (catch empty)]]
- [[1. What is the difference between checked and unchecked exceptions]]
- [[20. What does the throws keyword do]]