Question 17 · Section 7

What does the printStackTrace() method do?

printStackTrace() - a Throwable method that outputs full exception information (type, message, call stack) to System.err.

Language versions: English Russian Ukrainian

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

  1. Exception type: java.lang.ArithmeticException
  2. Message: / by zero
  3. 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:

  1. Writes to System.err, not to your log file. In production, logs are collected centrally (ELK, Splunk), and System.err may be redirected to /dev/null or lost on container restart
  2. Adds no context: no timestamp, trace ID, class name - just bare stack. Try finding the right error among thousands like it
  3. 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
  4. Blocks the thread - System.err is synchronized. Under high load, 100 threads will queue for writing

When NOT to use printStackTrace()

  1. Production code - replace with logger (log.error("msg", e))
  2. Multithreaded applications - System.err is synchronized, creates contention
  3. Web applications - stack in HTTP response exposes internal structure (Security)
  4. ELK/Splunk infrastructures - printStackTrace() splits one stack into 50+ separate JSON records
  5. Highload systems - blocking on System.err when 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 threads
  • jcmd <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 to System.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 - PrintStream with 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 + PrintWriter or ExceptionUtils.getStackTrace(e) from Apache Commons
  • What happens on disk full? - printStackTrace() blocks thread indefinitely, since System.err is synchronized
  • How to avoid stack leakage in HTTP response in Spring? - Use @ControllerAdvice, never return printStackTrace() 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]]