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

ConstantBootstraps.explicitCast contradictory specification for null-to-primitive

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      The java.lang.invoke.ConstantBootstraps.explicitCast method does not behave as documented when converting a null value to a primitive type. Instead of throwing a ClassCastException as its specification mandates, it silently returns the primitive's default zero value (e.g., 0 for int).

      The core of this issue lies in a conflict between the high-level contract of explicitCast and the behavior of the lower-level mechanism it uses for its implementation.

      The explicitCast Contract
      The Javadoc for java.lang.invoke.ConstantBootstraps.explicitCast provides a clear specification for this case. It states:
      "If dstType is a primitive type, then, if the runtime type of value is a primitive wrapper type (such as Integer), a Java unboxing conversion is applied ... If the runtime type of value is not a primitive wrapper type a ClassCastException is thrown."

      The input value in the test case is null. The runtime type of null is not a primitive wrapper type. Therefore, according to this contract, a ClassCastException is required.

      The Underlying Implementation's Behavior

      The observed behavior (returning 0) stems from explicitCast delegating the conversion to java.lang.invoke.MethodHandles.explicitCastArguments. The documentation for MethodHandles.explicitCastArguments describes a different handling for null:

      "If T0 is a reference and T1 a primitive, and if the reference is null at runtime, a zero value is introduced."

      This perfectly explains why 0 is returned. The explicitCast method's implementation relies on explicitCastArguments, which has a specific, documented rule to convert a null reference to a primitive's default value. The problem is that explicitCast uses this mechanism without adding the check required to fulfill its own, more stringent, documented contract.

      Maybe clarify JavaDoc is helpful


      ---------- BEGIN SOURCE ----------
      import java.lang.invoke.ConstantBootstraps;

      public class ExplicitCastBug {
          public static void main(String[] args) {
              System.out.println("Attempting to cast null to int via ConstantBootstraps.explicitCast...");
              try {
                  // This call should throw ClassCastException according to the documentation.
                  Object result = ConstantBootstraps.explicitCast(null, null, int.class, null);
                  
                  // This line is reached, which is incorrect.
                  System.out.println("BUG: The call succeeded and returned: " + result);
                  System.out.println("Expected a ClassCastException, but none was thrown.");
              } catch (ClassCastException e) {
                  // This block is never reached.
                  System.out.println("SUCCESS: Correctly caught the expected ClassCastException.");
                  e.printStackTrace();
              }
          }
      }
      ---------- END SOURCE ----------

            liach Chen Liang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: