Как передача оригинального exception влияет на трассировку стека
Что проверяют
Понимаете ли вы, когда в Java заполняется трассировка стека и что теряется при перевыбросе. Следом просят прочитать реальный стектрейс с блоком Caused by и объяснить, что значит строка ... 12 more.
Как отвечать
Стек записывается в момент создания исключения: конструктор Throwable вызывает fillInStackTrace(). Отсюда три случая:
throw e;вcatch: исключение то же, трассировка исходная, место перевыброса в ней не появится;- обёртка с причиной:
throw new ServiceException("Заказ не загружен", e)илиinitCause(e). У нового исключения свой стек от места обёртки, а исходное печатается ниже в блокеCaused by:со своей трассировкой. Строка... N moreозначает, что последние N кадров совпадают с кадрами внешнего исключения и не повторяются; - обёртка без причины:
new ServiceException(e.getMessage()). Исходный тип и стек потеряны, в логе видно только место обёртки.
Цепочку можно пройти через getCause(), в Apache Commons Lang есть ExceptionUtils.getRootCause. В try-with-resources исключение при закрытии ресурса не затирает основное, а прикрепляется через addSuppressed и печатается в блоке Suppressed:.
Хорошо упомянуть цену: сбор стека заметно дороже самого throw. Для исключений, которые служат сигналом в горячем коде, есть защищённый конструктор Throwable(message, cause, enableSuppression, writableStackTrace) с отключённой записью стека.
Где спотыкаются
Логируют log.error("Ошибка: " + e) или log.error(e.getMessage()). В лог уходит одна строка без стека. В SLF4J исключение передают последним аргументом: log.error("Заказ {} не загружен", id, e).
Удивляются исключениям без стека в логах прода. Это оптимизация HotSpot OmitStackTraceInFastThrow: после многих повторов JIT начинает бросать заранее созданные NullPointerException и подобные без трассировки. Отключается флагом -XX:-OmitStackTraceInFastThrow.
Оборачивают на каждом слое. Цепочка из пяти Caused by с одинаковым смыслом читается хуже, чем одна обёртка на границе слоя с добавленным контекстом: какой заказ, какой запрос.