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

Type-checked ConstantPool.entryByIndex and ClassReader.readEntryOrNull

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 23
    • core-libs
    • None
    • source
    • minimal
    • Changes to preview APIs involve minimal risk.
    • Java API
    • SE

      Summary

      Add ConstantPool.entryByIndex and ClassReader.readEntryOrNull, and remove ClassReader.utf8EntryByIndex.

      Problem

      Many constant pool references in ClassFile structures are restricted to a particular type, otherwise it's an error; for example, the superclass pointer can be 0 (null) or a valid CONSTANT_Class index, but not a CONSTANT_Utf8 index. However, the methods in ClassFile API only provides a readEntryOrNull without type checking, and a cast to ClassEntry may cause ClassCastException, which is out of spec with ClassFile API throwing IllegalArgumentException for malformed Class-Files.

      Solution

      1. Add overloads to ConstantPool.entryByIndex and ClassReader.readEntryOrNull.
      2. Remove ClassReader.utf8EntryByIndex; users can use ConstantPool.entryByIndex(index, Utf8Entry.class).
      3. Add API notes on entryByIndex, readEntry, readEntryOrNull to recommend using type-checked methods to access constant pool if there's a type restriction.

      Specification

      --- a/src/java.base/share/classes/java/lang/classfile/ClassReader.java
      +++ b/src/java.base/share/classes/java/lang/classfile/ClassReader.java
      @@ -89,17 +89,14 @@ public sealed interface ClassReader extends ConstantPool
      
           // Constant pool
      
      -    /**
      -     * {@return the UTF8 constant pool entry at the given index of the constant
      -     * pool}  The given index must correspond to a valid constant pool index
      -     * whose slot holds a UTF8 constant.
      -     * @param index the index into the constant pool
      -     */
      -    Utf8Entry utf8EntryByIndex(int index);
      -
           /**
            * {@return the constant pool entry whose index is given at the specified
            * offset within the classfile}
      +     *
      +     * @apiNote
      +     * If only a particular type of entry is expected, use {@link #readEntry(
      +     * int, Class) readEntry(int, Class)}.
      +     *
            * @param offset the offset of the index within the classfile
            * @throws ConstantPoolException if the index is out of range of the
            *         constant pool size, or zero
      @@ -121,12 +118,31 @@ public sealed interface ClassReader extends ConstantPool
            * {@return the constant pool entry whose index is given at the specified
            * offset within the classfile, or null if the index at the specified
            * offset is zero}
      +     *
      +     * @apiNote
      +     * If only a particular type of entry is expected, use {@link #readEntryOrNull(
      +     * int, Class) readEntryOrNull(int, Class)}.
      +     *
            * @param offset the offset of the index within the classfile
            * @throws ConstantPoolException if the index is out of range of the
            *         constant pool size
            */
           PoolEntry readEntryOrNull(int offset);
      
      +    /**
      +     * {@return the constant pool entry of a given type whose index is given
      +     * at the specified offset within the classfile, or null if the index at
      +     * the specified offset is zero}
      +     *
      +     * @param <T> the entry type
      +     * @param offset the offset of the index within the classfile
      +     * @param cls the entry type
      +     * @throws ConstantPoolException if the index is out of range of the
      +     *         constant pool size, or zero, or the entry is not of the given type
      +     * @since 24
      +     */
      +    <T extends PoolEntry> T readEntryOrNull(int offset, Class<T> cls);
      +
           /**
            * {@return the UTF8 entry whose index is given at the specified
            * offset within the classfile}
      --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java
      +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java
      @@ -46,6 +46,10 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
           /**
            * {@return the entry at the specified index}
            *
      +     * @apiNote
      +     * If only a particular type of entry is expected, use {@link #entryByIndex(
      +     * int, Class) entryByIndex(int, Class)}.
      +     *
            * @param index the index within the pool of the desired entry
            * @throws ConstantPoolException if the index is out of range of the
            *         constant pool, or is considered unusable
      @@ -57,6 +61,18 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
            */
           int size();
      
      +    /**
      +     * {@return the entry of a given type at the specified index}
      +     *
      +     * @param <T> the entry type
      +     * @param index the index within the pool of the desired entry
      +     * @param cls the entry type
      +     * @throws ConstantPoolException if the index is out of range of the
      +     *         constant pool, or the entry is not of the given type
      +     * @since 24
      +     */
      +    <T extends PoolEntry> T entryByIndex(int index, Class<T> cls);
      +
           /**
            * {@return an iterator over pool entries}
            */

            liach Chen Liang
            liach Chen Liang
            Adam Sotona
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: