我一直想知道为什么 JVM 不告诉你 哪个 当 a 时,指针(或更准确地说,哪个变量)为空 NullPointerException 被抛出。

行号不够具体,因为有问题的行通常包含许多可能导致错误的变量。

是否有任何编译器或 JVM 标志可以使这些异常消息更有用?

有帮助吗?

解决方案

这是因为反引用总是发生时,有没有可用的名称。的值被加载到操作数栈,并且然后被传递到该解引用它的操作码JRE之一。然而,操作数栈没有一个名字与空值相关联。它有的只是“空”。一些聪明的运行时跟踪代码,名称可以得出,但将有限的价值增加开销。

由于这个原因,没有JRE选项将会接通用于空指针的异常的额外信息。

在这个例子中,参考被存储在本地时隙1,它映射到本地变量名。但解除引用发生在invokevirtual指令,该指令只看到堆栈上的“空”值,然后将引发异常:

15 aload_1
16 invokevirtual #5 

同样有效。将数组负载后跟一个间接引用,但在这种情况下,没有名称映射到“空”值,只是一个索引了另一个值。

76 aload    5
78 iconst_0
79 aaload
80 invokevirtual #5

您不能静态分配的名称给每个指令会 - 这个例子中会产生大量的字节码的,但你可以看到,取消引用指令将接受或objA或objB,你需要动态地跟踪这种汇报正确的,因为这两个变量流向相同解除引用指令:

(myflag ? objA : objB).toString()

其他提示

一旦你JIT代码,它只是本地指针运算,如果在本机代码的任何指针是空的,它抛出异常。这将产生破坏性性能影响扭转这种组件回原始变量,并考虑到JIT优化生成的代码以不同水平,往往甚至不可能的。

如果你打破行成多行,而不是把若干方法调用在一行上,或者如果在该线路上设置断点,并通过与调试器的线步骤中,可以找出哪些引用为null很容易。

如果

线号不够具体,因为违规行通常包含可能导致错误的许多变量。

那么我建议:

  1. 将该行分成多行并分配可能的行 NullPointerException- 为临时变量生成值。
  2. 使用调试器并逐步执行每个方法调用,直到找到导致问题的方法。

这是不幸的不仅仅是Java的工作方式。

如果这是“你的”代码,然后简单地添加片段等

if (foo == null) {
  throw new NullPointerException("foo == null");
}

分配FOO之后。如果foo是则参数立即检查在方法本体的开始,并抛出IllegalArgumentException代替。

这会帮助你澄清事实。

您可以调试以获得异常的确切原因,当在Eclipse中的空指针异常添加一个断点。

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