Почему мое исключение NullPointerException не перехватывается в моем блоке catch?

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

Вопрос

У меня есть поток, в котором я улавливаю все ошибки в большом, всеобъемлющем блоке catch.Я делаю это для того, чтобы я мог сообщить о любой ошибке, а не только ожидаемой, в моем приложении.Мой Runnable выглядит следующим образом:

public final void run()
{
    try
    {
        System.out.println("Do things"); /* [1] */

        doUnsafeThings();
    }
    catch (Throwable t)
    {
        System.out.println("Catch"); /* [2] */

        recover();
    }
    finally
    {
        System.out.println("Finally"); /* [3] */
    }
}

Я бы ожидал, что NPE будет пойман блоком Throwable catch.Вместо этого выходные данные в [2] не печатаются, как и в [3].Выводится на печать в [1].

Что я действительно получаю на консоли, так это:

Uncaught exception java/lang/NullPointerException.

Что, черт возьми, здесь происходит?

Для судебных протоколов я использую J2ME, и это работает в эмуляторе Sun WTK v2.5.2.

У меня возникает соблазн списать это на изворотливость реализации JVM, но я не могу избавиться от ощущения, что я просто чего-то не понимаю.

Поясняю во избежание сомнений (поскольку пример кода явно изменен по сравнению с моим производственным кодом)

  • В методе run нет ничего за пределами блока try / catch/finally в методе run.
  • В начале каждого из этих блоков есть System.out.println - То, что следует за этими консольными инструкциями, не должно иметь значения.
Это было полезно?

Решение

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

Я на мгновение забыл, что поток, который запускал runnable, был пользовательским классом thread (чтобы обойти некоторые ошибки Nokia).Это называлось run() неоднократно между вызовами в canWait() способ.

Метод canWait был ответственен за сбой, а run вообще не был сбоем.В довершение всего, у меня консольная слепота, и я полностью, но случайно неправильно процитировал последовательность событий в моем вопросе.

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

Похоже, вам понадобятся некоторые методы проб и ошибок.Могу я предложить:

try {
    doEvilStuff();
} catch (NullPointerException ex) { 
    System.out.println("NPE encountered in body"); 
} catch (Throwable ex) {
    System.out.println("Regular Throwable: " + ex.getMessage());
} finally {
    etc...
}

Имея явный catch для NullPointerException, должно стать очевидным, является ли исключение из блока try или блока catch / finally .

Ладно, это смелое предположение...но это бы многое объяснило.

Очевидно, что ваш код не является на самом деле это - итак, я предполагаю, что ваш блок catch (или finally) либо что-то делает, прежде чем что-либо регистрировать, или он использует другой регистратор, чем блок try.В любом случае, я подозреваю, что либо блок catch, либо блок finally генерируют исключение.

Я не предполагаю, что у вас есть трассировка стека...

Редактировать:Хорошо, если это просто System.out.println, есть ли в этом споре что-то такое, что может взорваться?Например:

catch (Throwable t) {
    // Will go bang if t.getCause() returns null
    System.out.println(t.getCause().getMessage());
}

Если это просто System.out.println("Constant") тогда это очень странно.

Знаете ли вы (напримериз строк журнала внутри блока try) как далеко на самом деле продвинулся блок try?

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

Если вы предоставили нам трассировку стека, вы можете получить лучшую помощь.

Когда я пытаюсь перехватить исключения, я делаю что-то вроде этого:

try {
  doSomethingBad();
} catch(Exception e) {
   try {
      LogException(...);
   } catch(Exception e) {}       
} finally {
}

Мне не нравится вкладывать исключения, но мне не нравится, что мой блок catch генерирует исключения.

Как вы упомянули, вы используете Runnable - это случайно не означает, что вы также используете несколько потоков?Если в doUnsafeThings() метод снова внутренне порождает другой поток, и это создает исключение, вы можете не получить его в потоке, которым является ваш блок catch.Видишь http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread .UncaughtExceptionHandler.html

Как правило, перехватывать исключение NullPointerException - плохая практика.

Программисты обычно перехватывают исключение NullPointerException при трех обстоятельствах:

The program contains a null pointer dereference. Catching the resulting exception was easier than fixing the underlying problem.
The program explicitly throws a NullPointerException to signal an error condition.
The code is part of a test harness that supplies unexpected input to the classes under test. 

Из этих трех обстоятельств приемлемо только последнее.перейдя по этой ссылке:

Поймать исключение NullPointerException

Возможно ли, что поток прерывается каким-то другим кодом?В общем случае блок finally всегда выполняется, если поток не завершается ненормально, либо System.exit(), либо чем-то подобным.

  • Вы уверены, что смотрите в нужном месте кода?Т.е. является ли блок doUnsafeThings(), который вы защищаете, частью трассировки стека?

  • Может быть, есть проблема с вашим методом сборки, и вы отлаживаете старую версию кода?

просто добавьте немного протоколирования в doUnsafeThings();чтобы увидеть, делает ли этот метод то, что вы ожидаете (например, установите try catch наконец и запишите что-нибудь)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top