考虑以下代码:
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专家,你有什么看法?
答案 0 :(得分:6)
为什么JVM也不能发出帮助消息
首先,JVM 可以执行此操作。例如,对于NullPointerExceptions,ClassCastExceptions等,SAP JVM确实provides extended messages。
对于HotSpot JVM,有requests做同样的事情,但由于@StephenC回答中提到的原因,它们被关闭为Will-Not-Fix。
但是,可以在JVM TI agent的帮助下丰富NullPointerException消息。
答案 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(不会修复)结束。没有理由(公开)。