JDK-8227717 : Give more helpful NullPointerException messages and add flag -XX:ShowCodeDetailsInExceptionMessages
  • Type: CSR
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 14
  • Submitted: 2019-07-16
  • Updated: 2020-05-08
  • Resolved: 2019-09-13
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Add new messages to NullPointerExceptions that precisely specify the location of the exception in code.

Add a manageable flag called -XX:ShowCodeDetailsInExceptionMessages to configure the content of exception messages as above new message.

Problem
-------

NullPointerExceptions do not clearly specify where the exception occurred, i.e., if there are several object references dereferenced in one line of code, the current empty message along with the line number does not specify which of these references is null.  

Exception messages could contain snippets of (static) code to give details of the problem causing the exception. Some users may not want to expose such code snippets in exception messages.


Solution
--------
Add messages to NullPointerExceptions raised in a line of code as `a.b.c.i = 99;` that tell where the exception occurred, as `Cannot assign field 'i' because 'a.b.c' is null.`  

To configure messages that contain snippets of code as `a.b.c`, add a manageable flag called -XX:ShowCodeDetailsInExceptionMessages.


Specification
-------------

The new NullPointerException message is described in detail in JEP 358 (https://openjdk.java.net/jeps/358). It improves messages of NPEs thrown by the Java Virtual Machine when it fails to execute a bytecode because it needs to dereference a null reference. When the exception is raised by the JVM's runtime, the bytecode that failed to execute is known. Looking at the previously executed bytecodes, the access path leading to the null reference is reconstructed and the message text is generated. Whether this message is printed can be configured with ShowCodeDetailsInExceptionMessages.

ShowCodeDetailsInExceptionMessages is a boolean flag. If it is `false`, messages containing snippets of code as in above example are not printed. If the flag is `true`, the messages are printed. `true` is the intended long-term default value, but it was agreed to switch the NullPointerException message off, first. Thus, the default first will be `false`.

The flag's help message is "Show exception messages from RuntimeExceptions that contain snippets of the failing code. Disable this to improve privacy."
Comments
Re-reviewed the CSR and JEP text; moving to Approved.
13-09-2019

The name was changed to ShowCodeDetailsInExceptionMessage.
14-08-2019

There are no general rules that I am aware of regarding the name of a flag and how it relates to its initial or "final" default - we have EnableXXX flags that are true and DisableXXX flags that are false. But in fact in hotspot EnableXXX and DisableXXX are very rarely used. More commonly we use UseXXX - and they may be true or false by default. That said we also use explicit <verb>XXX forms. There already exists `SuppressFatalErrorMessage` (default false) so `SuppressCodeDetailsInExceptionMessages` is consistent with that form.
23-07-2019

It was considered to call the flag 'Enable...', but as it is intended to have the feature on per default in a later release, that would result in an inverted flag in the final state. Do I need to specify the precise message printed in the exception? You had told me not to. What exactly should I specify in more detail instead of refering to the JEP? I'll extend the description a bit. Yes, it can be changed dynamically. It only controls whether the algorithm to compute the message is called from NullPointerException::getMessage(). There is no state / initialization etc.. It was requested by Oracle to make it a managable flag. I can imagine to reuse the flag for other, similar exception message improvements. I.e., to improve the message of exceptions raised by the JVM runtime as ArrayIndexOutOfBounds or ArithmeticExceptions. It is thinkable to use the flag in Java code throwing exceptions, but I think in that case it is unlikely that "CodeSnippets" are useful in the exception message. As there the exception is raised for a certain condition, it should be possible to give more precise context in the message. The source of the exception should be clear in that case anyways. I am not aware of any special handling needed for invokedynamic. There is special handling for so-called "hidden frames". These are not reported in the stack trace. If this is the case, the message is omitted too, as it would reference code in a method that does not appear in the stack trace.
23-07-2019

Was there consideration given to a name like "EnableCodeDetailsInExceptionMessages" so that the sense of the true/false value of setting the option are not inverted? Not that the CSR covers a particular snapshot of a change so if there are specific interfaces being modified, just referring to a JEP is not sufficient since the JEP can be changed independently of the CSR. In particular, a JEP can be modified after a CSR is approved. As a manageable flag does that mean it can be changed dynamically at runtime? For future work, has limiting the flag's effects to JDK code or non-JDK code been considered? (In analogy to "enable system assertions" and "enable assertions". Is there any special handling to be done for invokedyanamic, method handles, etc? Moving to Provisional.
23-07-2019

"Interface Kind" I'm not sure what to tick for a change in exception message.
16-07-2019