java 为什么我的 NullPointerException 没有被我的 catch 块捕获?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/776765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:43:17  来源:igfitidea点击:

Why is my NullPointerException not being caught in my catch block?

javaexceptionjava-metry-catchjava-wireless-toolkit

提问by izb

I have a thread in which I catch all errors in a big, all-encompassing catch block. I do this so that I can report any error, not just expected ones, in my application. My Runnable looks like this:

我有一个线程,我在一个大的、包罗万象的 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] */
    }
}

I would expect the NPE to be caught by the Throwable catch block. Instead, the output at [2] is not printed, and neither is [3]. The output at [1] is printed.

我希望 NPE 会被 Throwable 捕获块捕获。相反,[2] 的输出不会被打印,[3] 也不会被打印。打印 [1] 处的输出。

What I do get on the console, is this:

我在控制台上得到的是:

Uncaught exception java/lang/NullPointerException.

What on earth is going on here?

这到底是怎么回事?

For the court records, I'm using J2ME, and this is running in Sun's WTK v2.5.2 emulator.

对于法庭记录,我使用的是 J2ME,它在 Sun 的 WTK v2.5.2 模拟器中运行。

I'm tempted to put it down to JVM implementation dodginess but I can't help feeling that I'm just missing something.

我很想把它归结为 JVM 实现的狡猾,但我不禁觉得我只是错过了一些东西。

To clarify for the avoidance of doubt (Since the example code is obviously altered from my production code)

澄清以避免疑问(因为示例代码显然是从我的生产代码中改变的)

  • There is nothing outside of the try/catch/finally block in the run method.
  • There is a System.out.println at the start of each of those blocks - What follows those console statements should not matter.
  • run 方法中的 try/catch/finally 块之外没有任何内容。
  • 每个块的开头都有一个 System.out.println - 这些控制台语句后面的内容无关紧要。

回答by izb

The answer turns out that I'm an idiot. I'd explain what went wrong, but let's just call it "one of those bugs".

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

I had momentarily forgotten that the thread that ran the runnable was a custom thread class (To get round some Nokia bugs). It called run()repeatedly between calls to a canWait()method.

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

The canWait method was responsible for the failure, and run wasn't failing at all. To top it off, I have console-blindness and completely but accidentally misquoted the sequence of events in my question.

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

回答by Mike

Sounds like you'll need some trial and error. May I suggest:

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

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

By having an explicit catch for NullPointerException, it should become obvious if the exception is from within the try block or a catch/finally block.

通过对 NullPointerException 进行显式捕获,很明显异常是来自 try 块还是 catch/finally 块。

回答by Jon Skeet

Okay, this is a wild guess... but it would explain things.

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

Obviously your code isn't actuallythat - so my guess is that your catch (or finally) block is either doing something before it logs anything, orit uses a different logger than the try block. Either way, I suspect that either the catch or the finally block is throwing the exception.

显然,您的代码实际上并非如此 - 所以我的猜测是您的 catch(或 finally)块要么在记录任何内容之前做某事,要么使用与 try 块不同的记录器。无论哪种方式,我都怀疑 catch 或 finally 块正在抛出异常。

I don't suppose you have a stack trace...

我不认为你有堆栈跟踪...

EDIT: Okay, if it's just System.out.println, is it something in the argument that might go bang? For example:

编辑:好的,如果只是System.out.println,它是否在争论中可能会爆炸?例如:

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

If it's just simple System.out.println("Constant")then it's very weird.

如果它只是简单的System.out.println("Constant")那么它是非常奇怪的。

Do you know (e.g. from log lines within the try block) how far the try block is actually getting?

您是否知道(例如,从 try 块中的日志行)try 块实际运行了多远?

回答by Daniel Schneller

As you mention you are using a Runnable- does this by any chance mean that you are using multiple threads as well? If the doUnsafeThings()method internally spawns a different thread again and that produces the exception, you might not get it in the thread your catch block is. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html

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

回答by James Black

When I looked at your code it seems that recover() is throwing an exception, so the advice given by Jon would be excellent to follow.

当我查看您的代码时,似乎 recovery() 正在抛出异常,因此 Jon 给出的建议非常适合遵循。

If you gave us a stack trace you may get better help.

如果你给了我们一个堆栈跟踪,你可能会得到更好的帮助。

When I try to catch exceptions I do something like this:

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

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

I don't like to nest exceptions, but I don't like my catch block throwing exceptions.

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

回答by za_al

It is generally a bad practice to catch NullPointerException.

捕获 NullPointerException 通常是一种不好的做法。

Programmers typically catch NullPointerException under three circumstances:

程序员通常在三种情况下捕获 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. 

Of these three circumstances, only the last is acceptable. following this link:

在这三种情况中,只有最后一种是可以接受的。按照这个链接:

Catch NullPointerException

捕捉空指针异常

回答by mfx

  • Are you sure you are looking at the right place in the code? I.e., is the doUnsafeThings() block you are protecting in of the stack trace?

  • Maybe there is a problem with your build method, and you are debugging an old version of the code?

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

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

回答by silmx

just add some logging in the doUnsafeThings(); to see if that method is doing what you expect (e.g put a try catch finally and log something)

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

回答by u7867

Is it possible that the thread is being killed by some other code? In general a finally block always executes unless the thread is abnormally terminated, either by System.exit() or something similar.

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