Почему мое NullPointerException не перехватывается в моем блоке перехвата? - PullRequest
4 голосов
/ 22 апреля 2009

У меня есть поток, в котором я перехватываю все ошибки в большом, всеобъемлющем блоке перехвата. Я делаю это так, чтобы я мог сообщать о любых ошибках, не только ожидаемых, в моем приложении. Мой 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 будет захвачен бросающим уловом. Вместо этого вывод в [2] не печатается, как и [3]. Вывод на [1] печатается.

Что я получаю на консоли, это:

Uncaught exception java/lang/NullPointerException.

Что здесь происходит?

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

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

Для уточнения во избежание сомнений (поскольку код примера явно отличается от моего производственного кода)

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

Ответы [ 9 ]

6 голосов
/ 22 апреля 2009

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

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

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

5 голосов
/ 22 апреля 2009

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

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

Наличие явного перехвата для NullPointerException должно стать очевидным, если исключение находится внутри блока try или блока catch / finally.

4 голосов
/ 22 апреля 2009

Хорошо, это дикое предположение ... но это могло бы объяснить вещи.

Очевидно, ваш код не на самом деле , что - так что я предполагаю, что ваш блок catch (или, наконец,) что-то делает, прежде чем что-то регистрирует, или использует другой logger, чем блок 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?

2 голосов
/ 22 апреля 2009

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

2 голосов
/ 22 апреля 2009

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

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

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

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

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

1 голос
/ 17 ноября 2012

Обычно перехватывать 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. 

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

Catch NullPointerException

0 голосов
/ 22 апреля 2009

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

0 голосов
/ 22 апреля 2009
  • Вы уверены, что смотрите в нужном месте кода? То есть, является ли блок doUnsafeThings (), который вы защищаете, в трассировке стека?

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

0 голосов
/ 22 апреля 2009

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

...