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

MHs.arrayLength, arrayElementGetter/Setter, arrayConstructor need to specify invocation-time behavior

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P2
    • Resolution: Approved
    • Fix Version/s: 10
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      Hide
      MethodHandle.asSpreader will throw NPE if the supplied array argument in null and the method handle expects non-zero length array argument. In JDK 9, IAE is thrown instead. The change of the exception type (NPE instead of IAE) should have minimal impact to existing application since invoking the spreader method handle with null array is an error case.
      Show
      MethodHandle.asSpreader will throw NPE if the supplied array argument in null and the method handle expects non-zero length array argument. In JDK 9, IAE is thrown instead. The change of the exception type (NPE instead of IAE) should have minimal impact to existing application since invoking the spreader method handle with null array is an error case.
    • Interface Kind:
      Java API
    • Scope:
      SE

      Description

      Summary

      Specify the invocation behavior of the method/var handle returned by MethodHandles factory methods: arrayLength, arrayConstructor, arrayElementGetter, arrayElementSetter, arrayElementVarHandle and MethodHandle::asSpreader method

      Problem

      Runtime-exception thrown when the method handle produced by the MethodHandles factory methods is invoked but not specified.

      Solution

      Specify the invocation behavior and exceptions thrown and method handle emulates the bytecode behavior.

      Specification

      Spec change in java.lang.invoke.MethodHandles class

           /**
      -     * Produces a method handle constructing arrays of a desired type.
      +     * Produces a method handle constructing arrays of a desired type,
      +     * as if by the {@code anewarray} bytecode.
            * The return type of the method handle will be the array type.
            * The type of its sole argument will be {@code int}, which specifies the size of the array.
      +     *
      +     * <p> If the returned method handle is invoked with a negative
      +     * array size, {@code NegativeArraySizeException} will be thrown.
      +     *
            * @param arrayClass an array type
            * @return a method handle which can create arrays of the given type
            * @throws NullPointerException if the argument is {@code null}
            * @throws IllegalArgumentException if {@code arrayClass} is not an array type
            * @see java.lang.reflect.Array#newInstance(Class, int)
      +     * @jvms 6.5 {@code anewarray} Instruction
            * @since 9
            */
      public static MethodHandle arrayConstructor(Class<?> arrayClass) throws IllegalArgumentException {
      
           /**
      -     * Produces a method handle returning the length of an array.
      +     * Produces a method handle returning the length of an array,
      +     * as if by the {@code arraylength} bytecode.
            * The type of the method handle will have {@code int} as return type,
            * and its sole argument will be the array type.
      +     *
      +     * <p> If the returned method handle is invoked with a {@code null}
      +     * array reference, {@code NullPointerException} will be thrown.
      +     *
            * @param arrayClass an array type
            * @return a method handle which can retrieve the length of an array of the given array type
            * @throws NullPointerException if the argument is {@code null}
            * @throws IllegalArgumentException if arrayClass is not an array type
      +     * @jvms 6.5 {@code arraylength} Instruction
            * @since 9
            */
      public static MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException {
      
           /**
      -     * Produces a method handle giving read access to elements of an array.
      +     * Produces a method handle giving read access to elements of an array,
      +     * as if by the {@code aaload} bytecode.
            * The type of the method handle will have a return type of the array's
            * element type.  Its first argument will be the array type,
            * and the second will be {@code int}.
      +     *
      +     * <p> When the returned method handle is invoked,
      +     * the array reference and array index are checked.
      +     * {@code NullPointerException} will be thrown if the array reference
      +     * is {@code null} and {@code ArrayIndexOutOfBoundsException} will be
      +     * thrown if the index is negative or if it is greater than or equal to
      +     * the length of the array.
      +     *
            * @param arrayClass an array type
            * @return a method handle which can load values from the given array type
            * @throws NullPointerException if the argument is null
            * @throws  IllegalArgumentException if arrayClass is not an array type
      +     * @jvms 6.5 {@code aaload} Instruction
            */
           public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
      
          /**
      -     * Produces a method handle giving write access to elements of an array.
      +     * Produces a method handle giving write access to elements of an array,
      +     * as if by the {@code astore} bytecode.
            * The type of the method handle will have a void return type.
            * Its last argument will be the array's element type.
            * The first and second arguments will be the array type and int.
      +     *
      +     * <p> When the returned method handle is invoked,
      +     * the array reference and array index are checked.
      +     * {@code NullPointerException} will be thrown if the array reference
      +     * is {@code null} and {@code ArrayIndexOutOfBoundsException} will be
      +     * thrown if the index is negative or if it is greater than or equal to
      +     * the length of the array.
      +     *
            * @param arrayClass the class of an array
            * @return a method handle which can store values into the array type
            * @throws NullPointerException if the argument is null
            * @throws IllegalArgumentException if arrayClass is not an array type
      +     * @jvms 6.5 {@code aastore} Instruction
            */
           public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
      
      
            * and atomic update access modes compare values using their bitwise
            * representation (see {@link Float#floatToRawIntBits} and
            * {@link Double#doubleToRawLongBits}, respectively).
      +     *
      +     * <p> When the returned {@code VarHandle} is invoked,
      +     * the array reference and array index are checked.
      +     * {@code NullPointerException} will be thrown if the array reference
      +     * is {@code null} and {@code ArrayIndexOutOfBoundsException} will be
      +     * thrown if the index is negative or if it is greater than or equal to
      +     * the length of the array.
      +     *
            * @apiNote
            * Bitwise comparison of {@code float} values or {@code double} values,
            * as performed by the numeric and atomic update access modes, differ
          public static VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {

      Spec change in java.lang.invoke.MethodHandle class

            * <p>
      -     * If, when the adapter is called, the supplied array argument does
      -     * not have the correct number of elements, the adapter will throw
      -     * an {@link IllegalArgumentException} instead of invoking the target.
      +     * When the adapter is called, the length of the supplied {@code array}
      +     * argument is queried as if by {@code array.length} or {@code arraylength}
      +     * bytecode. If the adapter accepts zero-length trailing array argument,
      +     * the supplied {@code array} argument can either be a zero-length array or
      +     * {@code null}; otherwise, the adapter will throw a {@code NullPointerException}
      +     * if {@code array} is {@code null} and throw an {@link IllegalArgumentException}
      +     * if {@code array} does not have the correct number of elements.
            * <p>
           public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                mchung Mandy Chung
                Reporter:
                slukyanov Stanislav Lukyanov (Inactive)
                Reviewed By:
                Paul Sandoz (Inactive), Roger Riggs
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: