Питання 17 · Розділ 7

Що робить метод printStackTrace()?

printStackTrace() — метод Throwable, який виводить повну інформацію про виняток (тип, повідомлення, стек викликів) у System.err.

Мовні версії: English Russian Ukrainian

Junior Level

Визначення

printStackTrace() — метод Throwable, який виводить повну інформацію про виняток (тип, повідомлення, стек викликів) у System.err.

Приклад

try {
    int x = 10 / 0;
} catch (ArithmeticException e) {
    e.printStackTrace();
    // Вивід: java.lang.ArithmeticException: / by zero
    //         at com.example.Main.main(Main.java:10)
}

Що він показує

  1. Тип винятку: java.lang.ArithmeticException
  2. Повідомлення: / by zero
  3. Стек викликів: у якому файлі, методі та рядку сталася помилка

Коли використовувати

  • Тільки при налагодженні та прототипуванні, коли вам потрібно швидко побачити стек у консолі без налаштування логера
  • Не використовувати у продакшен-коді

ЧОМУ printStackTrace() поганий для production

printStackTrace() — це «сирий» вивід, який:

  1. Пише в System.err, а не у ваш лог-файл. У production логи збираються централізовано (ELK, Splunk), а System.err може бути перенаправлений у /dev/null або втрачений при перезапуску контейнера
  2. Не додає контекст: немає timestamp, trace ID, імені класу — тільки голий стек. Спробуйте знайти потрібну помилку серед тисяч таких самих
  3. Розбиває стек на окремі рядки. У Kubernetes кожен рядок printStackTrace() стає окремим JSON-записом в ElasticSearch — замість одного читабельного логу ви отримуєте 50 розрізнених
  4. Блокує потікSystem.err синхронізований. При високій навантаженості 100 потоків стоятимуть у черзі на запис

Коли НЕ використовувати printStackTrace()

  1. Продакшен-код — замінюйте на логер (log.error("msg", e))
  2. Багатопоточні додаткиSystem.err синхронізований, створює contention
  3. Веб-додатки — стек у HTTP-відповіді розкриває внутрішню структуру (Security)
  4. ELK/Splunk інфраструктуриprintStackTrace() розбиває один стек на 50+ окремих JSON-записів
  5. Highload-системи — блокування на System.err при заповненому диску/pipe

Middle Level

Чому це працює повільно

1. Синхронізація: System.err — об’єкт PrintStream. Усі його методи використовують синхронізацію. У багатопоточному додатку 100 потоків чекатимуть блокування.

2. Перетворення нативного стека: Throwable ліниво перетворює нативний backtrace у масив StackTraceElement[] саме в момент звернення до стеку.

Вивід у рядок

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

Порівняння з логерами

// ПОГАНО — синхронізація, немає контексту, розбиває логи
e.printStackTrace();

// ДОБРЕ — асинхронно, з контекстом, JSON-friendly
log.error("Failed to process order id={}", id, e);

Логери вміють:

  • Форматувати стек в один рядок або JSON
  • Обрізати занадто довгі стеки
  • Додавати інформацію про JAR-файл та версію
  • Писати у файл, а не в консоль

Куди він пише насправді

В Kubernetes/Docker System.err перехоплюється і пишеться в JSON-логи. Але printStackTrace() виводить кожен рядок як окремий запис.

Результат: замість одного логу помилки — 50 розрізнених рядків в ElasticSearch.


Senior Level

Standard I/O blocking

Якщо диск переповнений або pipe консолі забитий, printStackTrace() заблокує потік виконання на невизначений час.

Senior Rule: у продакшен-коді printStackTrace() має бути заборонений правилами статичного аналізу (Checkstyle/Sonar).

Circular Causes

При циклічній залежності в cause (хоча initCause це перевіряє), printStackTrace має захист і друкує [CIRCULAR REFERENCE], не йдучи в нескінченну рекурсію.

Security

Стек-трейс у консолі розкриває версії бібліотек та структуру шляхів. У веб-додатках ніколи не віддавайте printStackTrace() у HTTP-відповіді — використовуйте @ControllerAdvice.

Альтернативи

// Програмово отримати стек як рядок
String stackTrace = ExceptionUtils.getStackTrace(e); // Apache Commons

// Логер
log.error("Context message", e); // Logback/Log4j2

// Thread Dumps — якщо додаток завис
// jstack <pid> або jcmd <pid> Thread.print

Діагностика

  • jstack <pid> — стан усіх моніторів та потоків
  • jcmd <pid> Thread.print — альтернатива jstack
  • Статичний аналіз — Sonar блокує printStackTrace() у продакшен-коді
  • JSON Layout — логи мають бути у форматі JSON для ELK/Splunk

🎯 Шпаргалка для інтерв’ю

Обов’язково знати:

  • printStackTrace() виводить тип, повідомлення та стек викликів винятку в System.err
  • НЕ використовувати в production: пише в System.err, а не в лог-файл; немає timestamp/trace ID; блокує потік (синхронізація)
  • В Kubernetes/Docker кожен рядок printStackTrace() стає окремим JSON-записом в ELK — один стек розбивається на 50+ записів
  • System.errPrintStream з синхронізацією; при високій навантаженості потоки стають у чергу
  • У продакшені замінюйте на log.error("context", e) — асинхронно, з контекстом, JSON-friendly
  • printStackTrace() захищає від циклічних причин — друкує [CIRCULAR REFERENCE]

Часті уточнюючі запитання:

  • Чому printStackTrace() поганий для production? — 4 причини: пише в System.err (не в лог), немає контексту, розбиває стек на рядки, блокує потік
  • Як отримати стек як рядок програмово?StringWriter + PrintWriter або ExceptionUtils.getStackTrace(e) з Apache Commons
  • Що відбувається при переповненні диска?printStackTrace() заблокує потік на невизначений час, т.к. System.err синхронізований
  • Як у Spring уникнути витоку стека в HTTP-відповідь? — Використовувати @ControllerAdvice, ніколи не віддавати printStackTrace() клієнту

Червоні прапорці (НЕ говорити):

  • “Використовую printStackTrace() у production — працює” — Втрачаєте логи, блокуєте потоки, розкриваєте структуру коду
  • “Різниці між printStackTrace() та логером немає” — Логер додає контекст, форматує, пише у потрібне місце
  • “Стек у HTTP-відповіді — нормальна практика” — Розкриває версії бібліотек та структуру шляхів (security vulnerability)

Пов’язані теми:

  • [[16. Що таке stack trace]]
  • [[18. Як правильно логовати винятки]]
  • [[20. Чому не варто ковтати винятки (порожній catch)]]
  • [[1. У чому різниця між checked та unchecked exceptions]]
  • [[21. Що робить ключове слово throws]]