3 min read

Developers frequently encounter NullPointerExceptions while developing or maintaining a Java application. They often don’t contain a message which makes it difficult for the developers to find the cause of the exception. Java Enhancement Proposal (JEP) proposes to enhance the exception text to notify what was null and which action failed.

For instance:

a.to_b.to_c = null;

a.to_b.to_c.to_d.num = 99;

The above code will print java.lang.NullPointerException and which doesn’t highlight what value is null.

A message like ‘a.to_b.to_c’ is null and cannot read field ‘to_d’ will highlight where the exception is thrown.

Basic algorithm to compute the message

In case of an exception, the instruction that caused the exception, is known by the virtual machine. The instruction gets stored in the ‘backtrace’ datastructure of a throwable object which is held in a field private to the jvm implementation.

In order to assemble a string as a.to_b.to_c, the bytecodes need to be visited in reverse execution order while starting at the bytecode that raised the exception.

If a developer or tester knows which bytecode pushed the null value, then it’s easy to print the message. A simple data flow analysis is run on the bytecodes to understand as to which previous instruction pushed the null value. This data flow analysis simulates the execution stack that does not contain the values computed by the bytecodes. Instead, it contains information about which bytecode pushed the value to the stack. The analysis will run until the information for the bytecode that raised the exception becomes available. With this information, it becomes easy to assemble the message.

An exception message is usually passed to the constructor of Throwable that writes it to its private field ‘detailMessage’. In case the message is computed only on access, then it can’t be passed to the Throwable constructor. Since the field is private, there is no natural way to store the message in it. To overcome this, developers can make detailMessage package-private or can use a shared secret for writing it or can write to the detailMessage field via JNI.

How should the message content be displayed

The message should only be printed if the NullPointerException is raised by the runtime. In case, the exception is explicitly constructed, it won’t make sense to add the message and it could be misleading as no NullPointerException was encountered.

As the original message won’t get regained so the message should try resembling code as possible. This makes it easy to understand and compact.

The message should contain information from the code like class names, method names, field names and variable names.

Testing done by the OpenJDK team

The basic implementation of testing for regressions of the messages is in use in SAP’s internal Java virtual machine since 2006. The team at OpenJDK has run all jtreg tests, many jck tests and many other tests on the current implementation. They have found no issues so far.

Proposed risks to it

This proposal has certain risks which include imposing overhead on retrieving the message of a NullPointerMessage. Though the risk of breaking something in the virtual machine is very low. The implementation needs to be extended in case more bytecodes are added to the Bytecode specification. Another issue that was raised is printing the field names or local names might impose a security problem.

To know more about this news, check out OpenJDK’s blog post.

Read Next

Introducing ‘Quarkus’, a Kubernetes native Java framework for GraalVM & OpenJDK HotSpot

The OpenJDK Transition: Things to know and do

Apache NetBeans IDE 10.0 released with support for JDK 11, JUnit 5 and more!