Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8341120

[lworld] NPE message can be wrong for null restricted fields

XMLWordPrintable

      Since JEP 358, NullPointerException are providing more information about the cause of the exception by describing precisely which variable is null.

      However, the current implementation of this extended description of the exception can produce erroneous message with null restricted fields.

      For instance, when running the following program:

      import jdk.internal.vm.annotation.NullRestricted;
      import jdk.internal.vm.annotation.ImplicitlyConstructible;
      import jdk.internal.vm.annotation.LooselyConsistentValue;

      public class NPETest {

          @ImplicitlyConstructible
          @LooselyConsistentValue
          static value class MyValue {
      int i = 0;
          }

          @NullRestricted
          MyValue val = new MyValue();

          public static void main(String[] args) {
      var test = new NPETest();
      test.val = null;
          }
      }

      The output is:

      $ java --enable-preview NPETest
      Exception in thread "main" java.lang.NullPointerException: Cannot assign field "val" because "<local1>" is null
      at NPETest.main(NPETest.java:18)

      When inspecting the NPETest class file, <local1> is the local variable containing the variable 'test' which is a newly created instance of NPETest and cannot be null at this point of the execution:

        public static void main(java.lang.String[]);
          descriptor: ([Ljava/lang/String;)V
          flags: (0x0009) ACC_PUBLIC, ACC_STATIC
          Code:
            stack=2, locals=2, args_size=1
               0: new #11 // class NPETest
               3: dup
               4: invokespecial #16 // Method "<init>":()V
               7: astore_1
               8: aload_1
               9: aconst_null
              10: putfield #10 // Field val:LNPETest$MyValue;
              13: return
            LineNumberTable:
              line 17: 0
              line 18: 8
              line 19: 13


      The cause of the NPE is the attempt to write the null reference (from the aconst_null) to a null restricted field.

      When JEP 358 was implemented, getfield and putfield had a single possible cause for throwing a NPE: a null receiver. So, the logic in ExceptionMessageBuilder::print_NPE_failed_action() was very simple.

      But the addition of null restriction to fields introduced a second possible source of NPE. Trying to determine the real cause of the NPE will be an implementation challenge, because it requires a deep knowledge of implementation of the component (interpreter/C1/C2) which was executing the bytecode to inspect the different internal variable an check them for null.

      A short term solution for the JEP 401 preview could be to have a slightly different NPE message for exceptions on null restricted fields, simply stating that either the receiver or the value is null. A better solution with a more accurate description of the cause of the NPE could be implemented later.


            Unassigned Unassigned
            fparain Frederic Parain
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: