【问题标题】:Why is my NullPointerException not being caught in my catch block?为什么我的 NullPointerException 没有被我的 catch 块捕获?
【发布时间】:2009-04-22 11:32:07
【问题描述】:

我有一个线程,我在一个大的、包罗万象的 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 块之外没有任何内容。
  • 每个块的开头都有一个 System.out.println - 这些控制台语句后面的内容无关紧要。

【问题讨论】:

  • 是否显示[1]处的输出?
  • 哦,斯基特先生,我可以要你的签名吗? :P

标签: java exception java-me try-catch java-wireless-toolkit


【解决方案1】:

答案原来是我是个白痴。我会解释出了什么问题,但我们就称它为“其中一个错误”。

我暂时忘记了运行 runnable 的线程是自定义线程类(为了绕过一些诺基亚错误)。它在调用canWait() 方法之间反复调用run()

canWait 方法导致了失败,并且 run 根本没有失败。最重要的是,我有控制台盲,并且完全但不小心错误地引用了我的问题中的事件顺序。

【讨论】:

  • 求知者想知道。我们都做过蠢事。
  • 我暂时忘记了运行 runnable 的线程是一个自定义线程类(为了绕过一些诺基亚错误)。它在调用“canWait()”方法之间重复调用 run()。 canWait 方法对失败负责,并且 run 根本没有失败。最重要的是,我有控制台失明,并且完全但不小心错误地引用了我的问题中的事件顺序。
【解决方案2】:

听起来您需要反复试验。我可以建议:

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 块中的异常应该会变得很明显。

【讨论】:

    【解决方案3】:

    好的,这是一个疯狂的猜测......但它可以解释事情。

    显然你的代码并不是实际上 - 所以我的猜测是你的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 块实际到达了多远?

    【讨论】:

    • 没有堆栈跟踪,没有(无法捕捉到它)。我刚才对我的问题的更新解决了你的一些答案。也没有涉及日志框架.. 只是 System.out.println。
    【解决方案4】:

    当我查看您的代码时,recover() 似乎正在引发异常,因此 Jon 给出的建议非常值得遵循。

    如果您向我们提供了堆栈跟踪,您可能会得到更好的帮助。

    当我尝试捕获异常时,我会这样做:

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

    我不喜欢嵌套异常,但我不喜欢我的 catch 块抛出异常。

    【讨论】:

      【解决方案5】:

      正如您提到的,您正在使用Runnable - 这是否意味着您也正在使用多个线程?如果doUnsafeThings() 方法在内部再次生成不同的线程并产生异常,则您可能无法在您的catch 块所在的线程中获取它。 见http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html

      【讨论】:

        【解决方案6】:

        捕获 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

        【讨论】:

        【解决方案7】:

        线程是否可能被其他代码杀死?一般来说,finally 块总是会执行,除非线程被 System.exit() 或类似的东西异常终止。

        【讨论】:

        • 不幸的是,这是不可能的。系统不退出,代码是为 CLDC 1.0(基本上是 Java API 的子集)构建的,这意味着没有办法终止线程。它不是 API 的一部分 - 线程仅在 run() 退出时退出。
        • 你能验证你的线程确实退出了吗?是否有可能线程仍然活着,但由于某个地方的异常而被阻塞,并且似乎只是从外部死亡?
        【解决方案8】:
        • 您确定您正在查看代码中的正确位置吗? 即,您要保护的 doUnsafeThings() 块是否位于堆栈跟踪中?

        • 可能你的构建方法有问题,你在调试旧版本的代码?

        【讨论】:

          【解决方案9】:

          只需在 doUnsafeThings() 中添加一些日志记录;看看那个方法是否在做你期望的事情(例如,最后放一个 try catch 并记录一些东西)

          【讨论】:

            猜你喜欢
            • 2012-02-24
            • 1970-01-01
            • 2010-09-07
            • 2016-02-03
            • 1970-01-01
            • 1970-01-01
            • 2010-11-16
            • 2012-01-22
            • 1970-01-01
            相关资源
            最近更新 更多