У меня были экземпляры нашей выгоды кода Java a NullPointerException
, но когда я пытаюсь зарегистрировать StackTrace (который в основном заканчивает тем, что звонил Throwable.printStackTrace()
), все, что я получаю:
java.lang.NullPointerException
Кто-либо еще столкнулся с этим? Я пытался гуглить для "нулевого указателя Java пустое отслеживание стека", но не сталкивался ни с чем как это.
Вы, вероятно, используете JVM HotSpot (первоначально Sun Microsystems, позже купленную Oracle, часть OpenJDK), которая выполняет большую оптимизацию. Чтобы вернуть трассировку стека, вам необходимо передать JVM параметр -XX: -OmitStackTraceInFastThrow
.
Оптимизация заключается в том, что когда исключение (обычно NullPointerException) возникает впервые, печатается полная трассировка стека, и JVM запоминает трассировку стека (или, может быть, просто местоположение кода).Когда это исключение возникает достаточно часто, трассировка стека больше не печатается, как для повышения производительности, так и для того, чтобы не переполнять журнал идентичными трассировками стека.
Чтобы увидеть, как это реализовано в JVM HotSpot, возьмите его копию и найдите глобальную переменную OmitStackTraceInFastThrow
. В последний раз, когда я смотрел код (в 2019 году), он находился в файле graphKit.cpp .
exception.toString
не дает вам StackTrace, он только возвращает
краткое описание этого бросаемого объекта. результатом является объединение:
* имени класса этого объекта * ":" (двоеточие и пробел) * результата вызова метода getLocalizedMessage () этого объекта
Используйте exception.printStackTrace
вместо этого для вывода StackTrace.
Альтернативное предложение - если вы используете Eclipse, вы можете установить точку останова на самом исключении NullPointerException (в перспективе «Отладка» перейдите на вкладку «Точки останова» и щелкните по маленькому значку с символом!)
Отметьте как «пойманный», так и «неперехваченный» параметры - теперь, когда вы запускаете NPE, вы сразу увидите точку останова, а затем вы сможете пройти через обрабатывается, и почему вы не получаете трассировку стека.
toString ()
возвращает только имя исключения и дополнительное сообщение. Я бы посоветовал позвонить
exception.printStackTrace()
, чтобы сбросить сообщение, или, если вам нужны кровавые подробности:
StackTraceElement[] trace = exception.getStackTrace()
Как вы упомянули в комментарии, вы используете log4j. Я обнаружил (непреднамеренно) место, где я написал
LOG.error(exc);
вместо типичного
LOG.error("Some informative message", e);
из-за лени или, возможно, просто не думая об этом. Самое неприятное в этом то, что оно ведет себя не так, как вы ожидаете. API регистратора на самом деле принимает Object в качестве первого аргумента, а не строку - и затем вызывает toString() для аргумента. Поэтому вместо того, чтобы получить красивый стековый след, он просто выводит toString - что в случае NPE довольно бесполезно.
Возможно, вы столкнулись именно с этим?
(Ваш вопрос до сих пор неясен, вызывает ли ваш код printStackTrace ()
или это выполняется обработчиком журнала.)
Вот несколько возможных объяснений того, что может происходить:
Используемый регистратор / обработчик настроен на вывод только строки сообщения об исключении, а не полной трассировки стека.
Ваше приложение (или какая-либо сторонняя библиотека) регистрирует исключение, используя LOG.error (ex);
, а не форму с двумя аргументами (например) метода log4j Logger.
Сообщение приходит откуда-то не там, где вы думаете; напримерна самом деле это какой-то сторонний библиотечный метод или какой-то случайный материал, оставшийся после предыдущих попыток отладки.
Регистрируемое исключение привело к перегрузке некоторых методов, чтобы скрыть трассировку стека. В этом случае исключение не будет настоящим исключением NullPointerException, а будет некоторым настраиваемым подтипом NPE или даже каким-либо несвязанным исключением.
Я думаю, что последнее возможное объяснение маловероятно, но люди, по крайней мере, задумываются о том, чтобы делать такие вещи, чтобы «предотвратить» реверс-инжиниринг. Конечно, это действительно усложняет жизнь честным разработчикам.
Мы видели такое же поведение в прошлом. Оказалось, что по какой-то безумной причине, если NullPointerException возникает в одном и том же месте кода несколько раз, через некоторое время использование Log.error (String, Throwable)
перестанет включать полные трассировки стека.
Попробуйте заглянуть дальше в свой журнал. Вы можете найти виновника.
РЕДАКТИРОВАТЬ: эта ошибка звучит актуально, но она была исправлена так давно, что, вероятно, не является причиной.
Это выведет исключение, используйте только для отладки, вам следует лучше обрабатывать исключения.
import java.io.PrintWriter;
import java.io.StringWriter;
public static String getStackTrace(Throwable t)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}