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

javac to null check immediately enclosing instance in inner class constructors

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P4 P4
    • 25
    • tools
    • None
    • behavioral
    • low
    • Hide
      There may be code using reflection or other JVM languages (raw bytecode) to exploit this lack of NPE to create instances and perform limited functionalities.

      Such usages are out of spec of the JLS, and any evolution in these inner classes that start using the enclosing instances can cause NPE and break such users; as a result, this is not a valid compatibility concern and the risk should be considered low.
      Show
      There may be code using reflection or other JVM languages (raw bytecode) to exploit this lack of NPE to create instances and perform limited functionalities. Such usages are out of spec of the JLS, and any evolution in these inner classes that start using the enclosing instances can cause NPE and break such users; as a result, this is not a valid compatibility concern and the risk should be considered low.
    • Class file construct
    • Implementation

      Summary

      Currently, an inner class instance with null enclosing instances can be created by reflection, method handles, or direct bytecode invocation. The java compiler's translation of inner class constructors will add a null check to the incoming immediately enclosing instance argument (unless this argument is delegated to another this() constructor call) to block such creations.

      Problem

      JLS provides that various use sites of inner class constructors should include null checks if the incoming immediately enclosing instance may be null, including for qualified instance creation expressions (JLS 15.9.4) and superconstructor invocations (JLS 8.8.7.1 "if the superclass constructor invocation is qualified"). Then, JLS assumes the enclosing instances are non-null in the usages in inner classes.

      However, JLS does not mandate any check in the declaration site of the inner class constructors. As a result, core reflection, method handles, or direct bytecode invocation may pass null for inner class constructors, and the usages of the enclosing instances later may see null and fail with an NPE.

      Solution

      javac will start emitting null checks in inner class constructors that calls a superclass constructor. Such constructors store to the synthetic field that captures the immediately enclosing instance. Other constructors all delegate to constructors that call superclass constructors.

      This is purely an implementation artifact with no JLS changes. In addition, these null checks will be emitted, even if the enclosing instance is unused and not stored into a field. These null checks will be emitted regardless of source or target releases.

      Note that the original compiler-generated null checks for the JLS 15.9.4 and 8.8.7.1 provisions are kept as-is. They currently causes an NPE before other exceptions can arise, such as any run-time LinkageError or any error thrown by the inner class constructors (such as one that calls a super constructor with a static method that throws an unchecked exception), which the checks added by this solution do not cover.

      Specification

      No change.

      It seems the word "instance" in the JLS means the presence of an object, as in "class instance", as opposed to null references. Therefore, null-checking a parameter that must pass an instance makes sense.

            liach Chen Liang
            webbuggrp Webbug Group
            Vicente Arturo Romero Zaldivar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: