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

Clarify API note in Class::getName and MethodType::toMethodDescriptorString

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 21, 22
    • core-libs
    • None
    • behavioral
    • minimal
    • Clarify existing specification.
    • Java API
    • SE

      Summary

      Update the API note of Class::getName, MethodType::fromMethodDescriptorString, and MethodType::toMethodDescriptorString to mention valid descriptors, distinct class loaders, and requirements for a truly inverse recovery of MethodType from a method type descriptor.

      Problem

      1. Class::descriptorString is not a partial inverse of Class::forName; Class::getName is when it returns a binary name.
      2. MethodType::toMethodDescriptorString has typos, and it and fromMethodDescriptorString doesn't mention hidden classes (whose resulting method types don't have method type descriptors) cannot be described nominally/constructed from descriptor.

      Solution

      1. Add a note about classes having same name but distinct loaders in getName, and remove the API notes from Class::descriptorString. (Note: JDK-8310242 mentions the relationship of getName and forName in forName's specification)
      2. Update MethodType::fromMethodDescriptorString to refer to method descriptors in JVMS to take non-nominally-describable classes into account
      3. Fix typos in MethodType::toMethodDescriptorString.

      Specification

      --- a/src/java.base/share/classes/java/lang/Class.java
      +++ b/src/java.base/share/classes/java/lang/Class.java
      @@ -946,6 +946,9 @@ public final class Class<T> implements java.io.Serializable,
            *     returns "[[[[[[[I"
            * </pre></blockquote>
            *
      +     * @apiNote
      +     * Distinct class objects can have the same name but different class loaders.
      +     *
            * @return  the name of the class, interface, or other entity
            *          represented by this {@code Class} object.
            * @jls 13.1 The Form of a Binary
      @@ -4562,11 +4565,6 @@ public final class Class<T> implements java.io.Serializable,
            * is a one-letter code corresponding to a primitive type or {@code void}
            * ({@code "B", "C", "D", "F", "I", "J", "S", "Z", "V"}) (JVMS {@jvms 4.3.2}).
            *
      -     * @apiNote
      -     * This is not a strict inverse of {@link #forName};
      -     * distinct classes which share a common name but have different class loaders
      -     * will have identical descriptor strings.
      -     *
            * @return the descriptor string for this {@code Class} object
            * @jvms 4.3.2 Field Descriptors
            * @since 12
      --- a/src/java.base/share/classes/java/lang/invoke/MethodType.java
      +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java
      @@ -1159,26 +1158,29 @@ class MethodType
           }
      
           /**
      -     * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
      -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
      +     * Finds or creates an instance of a method type of the given method descriptor
      +     * (JVMS {@jvms 4.3.3}). This method is a convenience method for
      +     * {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
            * Any class or interface name embedded in the descriptor string will be
      -     * resolved by the given loader (or if it is null, on the system class loader).
      -     * <p>
      -     * Note that it is possible to encounter method types which cannot be
      -     * constructed by this method, because their component types are
      -     * not all reachable from a common class loader.
      +     * resolved by the given loader (or if it is {@code null}, on the system class loader).
      +     *
      +     * @apiNote
      +     * It is possible to encounter method types that have valid descriptors but
      +     * cannot be constructed by this method, because their component types are
      +     * not visible from a common class loader.
            * <p>
            * This method is included for the benefit of applications that must
            * generate bytecodes that process method handles and {@code invokedynamic}.
      -     * @param descriptor a bytecode-level type descriptor string "(T...)T"
      +     * @param descriptor a method descriptor string
            * @param loader the class loader in which to look up the types
      -     * @return a method type matching the bytecode-level type descriptor
      -     * @throws NullPointerException if the string is null
      -     * @throws IllegalArgumentException if the string is not well-formed
      +     * @return a method type of the given method descriptor
      +     * @throws NullPointerException if the string is {@code null}
      +     * @throws IllegalArgumentException if the string is not a method descriptor
            * @throws TypeNotPresentException if a named type cannot be found
            * @throws SecurityException if the security manager is present and
            *         {@code loader} is {@code null} and the caller does not have the
            *         {@link RuntimePermission}{@code ("getClassLoader")}
      +     * @jvms 4.3.3 Method Descriptors
            */
           public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
               throws IllegalArgumentException, TypeNotPresentException
      @@ -1218,19 +1220,20 @@ class MethodType
           }
      
           /**
      -     * Returns a descriptor string for the method type.  This method
      +     * {@return the descriptor string for this method type} This method
            * is equivalent to calling {@link #descriptorString() MethodType::descriptorString}.
            *
      -     * <p>
      -     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
      -     * Two distinct classes which share a common name but have different class loaders
      -     * will appear identical when viewed within descriptor strings.
      +     * @apiNote
      +     * This is not a strict inverse of {@link #fromMethodDescriptorString
      +     * fromMethodDescriptorString} which requires a method type descriptor
      +     * (JVMS {@jvms 4.3.3}) and a suitable class loader argument.
      +     * Two distinct {@code MethodType} objects can have an identical
      +     * descriptor string as distinct classes can have the same name
      +     * but different class loaders.
      +     *
            * <p>
            * This method is included for the benefit of applications that must
            * generate bytecodes that process method handles and {@code invokedynamic}.
      -     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
      -     * because the latter requires a suitable class loader argument.
      -     * @return the descriptor string for this method type
            * @jvms 4.3.3 Method Descriptors
            * @see <a href="#descriptor">Nominal Descriptor for {@code MethodType}</a>
            */

      Rendered specifications:

      https://cr.openjdk.org/~liach/8309819/09/java.base/java/lang/Class.html

      https://cr.openjdk.org/~liach/8309819/09/java.base/java/lang/invoke/MethodType.html

        1. 8309819.00.patch
          3 kB
        2. 8309819.02.patch
          3 kB
        3. 8309819.03.patch
          4 kB
        4. 8309819.04.patch
          4 kB
        5. 8309819.06.patch
          7 kB
        6. 8309819.07.patch
          5 kB
        7. 8309819.09.patch
          5 kB

            liach Chen Liang
            liach Chen Liang
            Mandy Chung (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: