Исключение NullPointerException в Java без StackTrace

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

java.lang.NullPointerException

кто-нибудь сталкивался с этим? Я попытался найти "java null pointer empty stack trace", но не наткнулся ни на что подобное.

10 ответов


вы, вероятно, используете Sun JVM, который выполняет большую оптимизацию. Чтобы вернуть трассировки стека, вам нужно передать опцию -XX:-OmitStackTraceInFastThrow в JVM.

современные OpenJDK JVMs (1.8 и выше?), кажется, принять -XX:-OmitStackTraceInFastThrow флаг, а также (и оптимизация трассировки стека включена по умолчанию), а также.


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

LOG.error(exc);

вместо обычного

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

из-за лени или, возможно, просто не думать об этом. К несчастью, он ведет себя не так, как вы ожидаете. API logger фактически принимает объект в качестве первого аргумента, а не строку, а затем вызывает toString() в аргументе. Так что вместо того, чтобы получить хороший довольно stack trace, он просто распечатывает toString - что в случае NPE довольно бесполезно.

возможно, это то, что вы испытываете?


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

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

EDIT: эта ошибка звучит уместно, но это было исправлено так давно, что это, вероятно, не причина.


вот объяснение : Hotspot заставил исключения потерять свои следы стека в производстве-и исправление

я протестировал его на Mac OS X

  • java версия "1.6.0_26"
  • Java (TM) SE среда выполнения (build 1.6.0_26-b03-383-11A511)
  • Java HotSpot (TM) 64-разрядный сервер VM (сборка 20.1-b02-383, смешанный режим)

    Object string = "abcd";
    int i = 0;
    while (i < 12289) {
        i++;
        try {
            Integer a = (Integer) string;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

для этого конкретного фрагмента кода 12288 итераций (+частота?) кажется пределом, где JVM решила использовать предварительно выделенное исключение...


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

краткое описание этого throwable. Результатом является конкатенация:

* the name of the class of this object
* ": " (a colon and a space)
* the result of invoking this object's getLocalizedMessage() method

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


альтернативное предложение-если вы используете Eclipse, вы можете установить точку останова на самом NullPointerException (в перспективе отладки перейдите на вкладку "точки останова" и нажмите на маленький значок, который имеет! в нем)

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


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

exception.printStackTrace()

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

 StackTraceElement[] trace = exception.getStackTrace()

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

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

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

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

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

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

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


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

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();
    }

когда вы используете AspectJ в своем проекте, может случиться, что какой-то аспект скрывает свою часть трассировки стека. Например, сегодня у меня было:

java.lang.NullPointerException:
  at com.company.product.MyTest.test(MyTest.java:37)

эта трассировка стека была напечатана при запуске теста через surefire Maven.

С другой стороны, при запуске теста в IntelliJ была напечатана другая трассировка стека:

java.lang.NullPointerException
  at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67)
  at ...
  at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82)
  at ...
  at com.company.product.MyTest.test(MyTest.java:37)