NullPointerException в Java без StackTrace

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

java.lang.NullPointerException

Кто-нибудь еще сталкивался с этим? Я попробовал googling для "java null pointer empty stack trace", но не нашел ничего подобного.

Ответ 1

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

Современные JVM OpenJDK (1,8 и выше?), Похоже, принимают -XX:-OmitStackTraceInFastThrow а также оптимизируют трассировку стека по умолчанию).

Ответ 2

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

LOG.error(exc);

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

  • версия java "1.6.0_26"
  • Java (TM) SE Runtime Environment (сборка 1.6.0_26-b03-383-11A511)
  • 64-разрядная серверная виртуальная машина Java HotSpot TM (сборка 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 решил использовать предопределенное исключение...

Ответ 5

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

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

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

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

Ответ 6

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

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

Ответ 7

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

exception.printStackTrace()

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

 StackTraceElement[] trace = exception.getStackTrace()

Ответ 8

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

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

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

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

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

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

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

Ответ 9

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

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

Ответ 10

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

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

Эта трассировка стека была напечатана при запуске теста с помощью Maven surefire.

С другой стороны, при запуске теста в 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)