NullPointerException в Java без StackTrace

У меня были экземпляры нашей выгоды кода Java a NullPointerException, но когда я пытаюсь зарегистрировать StackTrace (который в основном заканчивает тем, что звонил Throwable.printStackTrace() ), все, что я получаю:

java.lang.NullPointerException

Кто-либо еще столкнулся с этим? Я пытался гуглить для "нулевого указателя Java пустое отслеживание стека", но не сталкивался ни с чем как это.

306
задан ДМИТРИЙ МАЛИКОВ 6 February 2013 в 01:48
поделиться

8 ответов

Вы, вероятно, используете JVM HotSpot (первоначально Sun Microsystems, позже купленную Oracle, часть OpenJDK), которая выполняет большую оптимизацию. Чтобы вернуть трассировку стека, вам необходимо передать JVM параметр -XX: -OmitStackTraceInFastThrow .

Оптимизация заключается в том, что когда исключение (обычно NullPointerException) возникает впервые, печатается полная трассировка стека, и JVM запоминает трассировку стека (или, может быть, просто местоположение кода).Когда это исключение возникает достаточно часто, трассировка стека больше не печатается, как для повышения производительности, так и для того, чтобы не переполнять журнал идентичными трассировками стека.

Чтобы увидеть, как это реализовано в JVM HotSpot, возьмите его копию и найдите глобальную переменную OmitStackTraceInFastThrow . В последний раз, когда я смотрел код (в 2019 году), он находился в файле graphKit.cpp .

365
ответ дан 23 November 2019 в 01:19
поделиться

exception.toString не дает вам StackTrace, он только возвращает

краткое описание этого бросаемого объекта. результатом является объединение:

 * имени класса этого объекта 
 * ":" (двоеточие и пробел) 
 * результата вызова метода getLocalizedMessage () этого объекта 
 

Используйте exception.printStackTrace вместо этого для вывода StackTrace.

10
ответ дан 23 November 2019 в 01:19
поделиться

Альтернативное предложение - если вы используете Eclipse, вы можете установить точку останова на самом исключении NullPointerException (в перспективе «Отладка» перейдите на вкладку «Точки останова» и щелкните по маленькому значку с символом!)

Отметьте как «пойманный», так и «неперехваченный» параметры - теперь, когда вы запускаете NPE, вы сразу увидите точку останова, а затем вы сможете пройти через обрабатывается, и почему вы не получаете трассировку стека.

4
ответ дан 23 November 2019 в 01:19
поделиться

toString () возвращает только имя исключения и дополнительное сообщение. Я бы посоветовал позвонить

exception.printStackTrace()

, чтобы сбросить сообщение, или, если вам нужны кровавые подробности:

 StackTraceElement[] trace = exception.getStackTrace()
1
ответ дан 23 November 2019 в 01:19
поделиться

Как вы упомянули в комментарии, вы используете log4j. Я обнаружил (непреднамеренно) место, где я написал

LOG.error(exc);

вместо типичного

LOG.error("Some informative message", e);

из-за лени или, возможно, просто не думая об этом. Самое неприятное в этом то, что оно ведет себя не так, как вы ожидаете. API регистратора на самом деле принимает Object в качестве первого аргумента, а не строку - и затем вызывает toString() для аргумента. Поэтому вместо того, чтобы получить красивый стековый след, он просто выводит toString - что в случае NPE довольно бесполезно.

Возможно, вы столкнулись именно с этим?

57
ответ дан 23 November 2019 в 01:19
поделиться

(Ваш вопрос до сих пор неясен, вызывает ли ваш код printStackTrace () или это выполняется обработчиком журнала.)

Вот несколько возможных объяснений того, что может происходить:

  • Используемый регистратор / обработчик настроен на вывод только строки сообщения об исключении, а не полной трассировки стека.

  • Ваше приложение (или какая-либо сторонняя библиотека) регистрирует исключение, используя LOG.error (ex); , а не форму с двумя аргументами (например) метода log4j Logger.

  • Сообщение приходит откуда-то не там, где вы думаете; напримерна самом деле это какой-то сторонний библиотечный метод или какой-то случайный материал, оставшийся после предыдущих попыток отладки.

  • Регистрируемое исключение привело к перегрузке некоторых методов, чтобы скрыть трассировку стека. В этом случае исключение не будет настоящим исключением NullPointerException, а будет некоторым настраиваемым подтипом NPE или даже каким-либо несвязанным исключением.

Я думаю, что последнее возможное объяснение маловероятно, но люди, по крайней мере, задумываются о том, чтобы делать такие вещи, чтобы «предотвратить» реверс-инжиниринг. Конечно, это действительно усложняет жизнь честным разработчикам.

1
ответ дан 23 November 2019 в 01:19
поделиться

Мы видели такое же поведение в прошлом. Оказалось, что по какой-то безумной причине, если NullPointerException возникает в одном и том же месте кода несколько раз, через некоторое время использование Log.error (String, Throwable) перестанет включать полные трассировки стека.

Попробуйте заглянуть дальше в свой журнал. Вы можете найти виновника.

РЕДАКТИРОВАТЬ: эта ошибка звучит актуально, но она была исправлена ​​так давно, что, вероятно, не является причиной.

27
ответ дан 23 November 2019 в 01:19
поделиться

Это выведет исключение, используйте только для отладки, вам следует лучше обрабатывать исключения.

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();
    }
0
ответ дан 23 November 2019 в 01:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: