Трассировка стека NullPointerException недоступна без агента отладки

StackOverflow https://stackoverflow.com/questions/1076191

Вопрос

Недавно я обнаружил ошибку, вызывающую исключение NullPointerException.Исключение перехватывается и регистрируется с помощью стандартного оператора slf4j.Сокращенный код ниже:

for(Action action : actions.getActions()) {
    try {
        context = action.execute(context);
    } catch (Exception e) {
        logger.error("...", e);
        break;
    }
}

Как видите, ничего особенного.Однако из всех имеющихся у нас операторов регистрации исключений только этот не печатает трассировку стека.Все, что он печатает, — это сообщение (представленное как «...») и имя класса исключения (java.lang.NullPointerException).

Поскольку трассировка стека для исключения загружается отложенно, я подумал, что, возможно, существует какая-то проблема с переупорядочением инструкций, и решил вызвать e.getStackTrace() перед оператором журнала.Это не имело никакого значения.

Поэтому я решил перезагрузить компьютер с включенным агентом отладки.Однако, поскольку я даже подключился к процессу, я заметил, что теперь печатаются трассировки стека.Очевидно, что присутствие агента отладки привело к тому, что стала доступна некоторая дополнительная отладочная информация.

С тех пор я исправил основную причину исключения.Но мне хотелось бы узнать, почему трассировка стека была недоступна без отладчика.Кто-нибудь знает?

Уточнение: это не проблема регистрации.Представьте себе то же самое предложение try/catch, но в catch я печатаю значение:

e.getStackTrace().length

Без отладчика выводится «0», с отладчиком — положительное число (в данном случае 9).

Больше информации:это происходит в JDK 1.6.0_13, 64-битной версии, amd64, Linux 2.6.9

Это было полезно?

Решение

Возможно ли, что этот код находится во внутреннем цикле?Тогда JIT-компилятор может компилировать стек вызовов для этого в собственный код, теряя информацию о стеке.Затем, когда вы подключаете отладчик, он отключает JIT, снова делая информацию доступной.

Другие исключения, создаваемые вручную, продолжают отображать информацию, поскольку JIT не выполняет оптимизацию.

Судя по комментарию в исходном коде этого класса в строке 102, похоже, что это может иногда происходить и с другими:

http://logging.apache.org/log4j/1.2/xref/org/apache/log4j/spi/LocationInfo.html

Другие советы

С помощью флага JVM -XX:-OmitStackTraceInFastThrow вы можете отключить оптимизацию производительности JVM для этого варианта использования.ЕСЛИ задан этот параметр, который отключает флаг, трассировка стека будет доступна.

Для получения дополнительной информации ознакомьтесь со следующими примечаниями к выпуску:

«Компилятор на серверной виртуальной машине теперь обеспечивает правильную обратную трассировку стека для всех «холодных» встроенных исключений.В целях повышения производительности, если такое исключение генерируется несколько раз, метод можно перекомпилировать.После перекомпиляции компилятор может выбрать более быструю тактику, используя предварительно выделенные исключения, которые не обеспечивают трассировку стека.Чтобы полностью отключить использование предварительно выделенных исключений, используйте этот новый флаг:-XX:-OmitStackTraceInFastThrow." http://java.sun.com/j2se/1.5.0/relnotes.html

Я могу повторить это, но мне кажется странным, что это происходит где-то в вашем действии.

Если вы вызовете setStackTrace с пустым массивом, это приведет к отображению только текста.

 public class Fark {
   public static void main(String[] args) {
       try {
           Fark.throwMe(args.length != 0);

       }
       catch (Exception e) {
           e.printStackTrace();
       }

   }

     public static final void throwMe(boolean arg) throws Exception{
         Exception e = new NullPointerException();
         if (arg) {
           e.setStackTrace(new StackTraceElement[0]);
         }
         throw e;
     }
 }

Запускаем это....

% java Fark
java.lang.NullPointerException
        at Fark.throwMe(Fark.java:15)
        at Fark.main(Fark.java:5)

% java Fark nothing
java.lang.NullPointerException
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top