我有一个线程,在一个大的、包罗万象的 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 - 这些控制台语句后面的内容并不重要。
有帮助吗?

解决方案

答案证明我是个白痴。我会解释出了什么问题,但我们姑且称之为“其中一个错误”。

我暂时忘记了运行可运行程序的线程是一个自定义线程类(为了解决一些诺基亚错误)。它叫 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...
}

通过对 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() 抛出了异常,因此 Jon 给出的建议非常值得遵循。

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

当我尝试捕获异常时,我会执行以下操作:

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. 

在这三种情况中,只有最后一种是可以接受的。点击此链接:

捕获空指针异常

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

  • 您确定您正在查看代码中的正确位置吗?即,您正在保护的 doUnsafeThings() 块是否位于堆栈跟踪中?

  • 也许您的构建方法有问题,并且您正在调试旧版本的代码?

只需在 doUnsafeThings() 中添加一些日志记录即可;看看该方法是否按照您的预期进行(例如,最后放置一个 try catch 并记录一些内容)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top