在NPE的情况下尝试进行操作

Jat*_*tin 13 java jvm

考虑以下代码:

String s = null;
s.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

它引发了一个NPE:


pracJava1.Prac.main 中线程"main"java.lang.NullPointerException 中的异常(Prac.java:7)

问题是:为什么JVM也不能发出帮助消息说:

线程"main"java.lang.NullPointerException中的异常.尝试toLowerCase() on null

这在类似的情况下很有用obj.setName(s.toLowerCase()),其中行号不足以猜测是否obj为null或s.


关于它的可行性,让我们看一下生成的字节码:

      stack=1, locals=2, args_size=1
     0: aconst_null
     1: astore_1
     2: aload_1
     3: invokevirtual #2    // Method java/lang/String.toLowerCase:()Ljava/lang/String;
Run Code Online (Sandbox Code Playgroud)

因此可能知道它尝试操作的方法名称.JVM专家,你有什么看法?

apa*_*gin 6

为什么JVM也不能发出帮助消息

首先,JVM 可以做到这一点.例如,SAP JVM确实为NullPointerExceptions,ClassCastExceptions等提供了扩展消息.

有人要求为HotSpot JVM做同样的事情,但由于@StephenC回答中提到的原因,它们因Will-Not-Fix而被关闭.

但是,可以在JVM TI代理的帮助下丰富NullPointerException消息.

扩展NPE消息的示例


Ste*_*n C 5

不这样做的一个可能原因是它可以破坏旧的Java代码.在开始的所有经典Java实现中,JVM本身抛出的NPE的消息属性已经存在null.

任何破坏旧应用程序代码的更改都会损害Java的Sun/Oracle业务模型.所有证据表明Sun/Oracle试图避免这种情况,除非替代方案更糟.

(偶尔会出现错误/误判,并且(可以说)不必要的"破坏"Java变更.我们看到了某些方面产生的"愤怒的嚎叫",我想Oracle也会通过他们的客户联系人得到反馈.)

Android"Java"的做法不同.(这表明NPE错误消息在Java中在技术上是可行的)但是Google并不需要担心旧的经典Java应用程序的兼容性.当替换大量标准Java SE库与Android替代品时,他们解决了这个问题.


你评论说:

但Oracle确实多次破坏了兼容性更改,其中api规范没有被破坏(但内部结构当然已经改变).如果有人正在解析NPE错误消息,我认为这不是一个足够好的理由:)

这些都是很好的争论点(也许).

但是,这个决定不公开辩论.这是Sun多年前做出的一项商业决策,Oracle已选择坚持.我们不知道真正的推理是什么.你或我对假设推理的看法没有任何影响.

据记载,这是2003年提出的RFE(JDK-4834738).该问题最终于2014年以WNF(不会修复)结束.没有理由(公开).