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

时间:2017-06-28 11:38:36

标签: java jvm

考虑以下代码:

String s = null;
s.toLowerCase();

它抛出一个NPE:

  

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

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

  

线程“main”java.lang.NullPointerException中的异常。试图toLowerCase() on null

这在类似obj.setName(s.toLowerCase())的情况下很有用,其中行号不足以猜测obj是否为空或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;

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

2 个答案:

答案 0 :(得分:6)

  

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

首先,JVM 可以执行此操作。例如,对于NullPointerExceptions,ClassCastExceptions等,SAP JVM确实provides extended messages

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

但是,可以在JVM TI agent的帮助下丰富NullPointerException消息。

The example of extending NPE messages

答案 1 :(得分:5)

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

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

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

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

您评论道:

  

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

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

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

为了记录,这在2003年被提议为RFE(JDK-4834738)。该问题最终在2014年以WNF(不会修复)结束。没有理由(公开)。