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)