JDK-8289419 : Add model of class file versions to core reflection
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 20
  • Submitted: 2022-06-28
  • Updated: 2022-08-08
  • Resolved: 2022-08-08
Related Reports
CSR :  
Description
Summary
-------
Add an `enum` class to model the class file format version and use those constants to return version-specific information about access flags.

Problem
-------

The applicability of access flags and other JVM structures are class file format version specific. Adding an `enum` class to model the versioning allows more precise information to be returned.

Solution
--------

Add `java/lang/reflect/ClassFileFormatVersion` as an `enum` class and add the method `AccessFlags.locations(ClassFileFormatVersion cffv)`.

Updating `ClassFileFormatVersion` would be part of the start-of-release set of changes.

Specification
-------------

    diff --git a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java
    index 785a9d798fd..5debc6fdaef 100644
    --- a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java
    +++ b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java
    @@ -70,7 +70,7 @@ import static java.util.Map.entry;
      * added at the end of the existing list.
      *
      * @apiNote
    - * The JVM class file format has a new version defined for each new
    + * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new
      * {@linkplain Runtime.Version#feature() feature release}. A new class
      * file version may define new access flags or retire old ones. {@code
      * AccessFlag} is intended to model the set of access flags across
    ...
    @@ -306,12 +455,23 @@ public enum AccessFlag {
         }
     
         /**
    -     * {@return kinds of constructs the flag can be applied to}
    +     * {@return kinds of constructs the flag can be applied to in the
    +     * latest class file format version}
          */
         public Set<Location> locations() {
             return locations;
         }
     
    +    /**
    +     * {@return kinds of constructs the flag can be applied to in the
    +     * given class file format version}
    +     * @param cffv the class file format version to use
    +     * @throws NullPointerException if the parameter is {@code null}
    +     */
    +    public Set<Location> locations(ClassFileFormatVersion cffv) {
    +        return locations; // Default to supported unchanging locations
    +    }
    +
         /**
          * {@return an unmodifiable set of access flags for the given mask value
          * appropriate for the location in question}
    
    diff --git a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java
    new file mode 100644
    index 00000000000..0faf46b2180
    --- /dev/null
    +++ b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java
    @@ -0,0 +1,350 @@
    
    +package java.lang.reflect;
    +
    +/**
    + * Class file format versions of the Java virtual machine.
    + *
    + * See the appropriate edition of <cite>The Java Virtual Machine
    + * Specification</cite> for information about a particular class file
    + * format version.
    + *
    + * <p>Note that additional class file format version constants will be
    + * added to model future releases of the Java Virtual Machine
    + * Specification.
    + *
    + * @since 20
    + * @see System#getProperties System property {@code java.class.version}
    + * @see java.compiler/javax.lang.model.SourceVersion
    + */
    +@SuppressWarnings("doclint:reference") // cross-module links
    +public enum ClassFileFormatVersion {
    +
    +    /**
    +     * The original version.
    +     *
    +     * The format described in <cite>The Java Virtual Specification,
    +     * First Edition</cite>.
    +     */
    +    RELEASE_0(45),
    +
    +    /**
    +     * The version recognized by the Java Platform 1.1.
    +     *
    +     * @apiNote
    +     * While {@code RELEASE_0} and {@code RELEASE_1} have the same
    +     * {@linkplain #major() major version}, several additional
    +     * attributes were defined for {@code RELEASE_1} (JVMS {@jvms
    +     * 4.7}).
    +     *
    +     */
    +    RELEASE_1(45),
    +
    +    /**
    +     * The version recognized by the Java 2 Platform, Standard Edition,
    +     * v 1.2.
    +     *
    +     * The format described in <cite>The Java Virtual Machine
    +     * Specification, Second Edition</cite>, which includes the {@link
    +     * AccessFlag#STRICT ACC_STRICT} access flag.
    +     */
    +    RELEASE_2(46),
    +
    +    /**
    +     * The version recognized by the Java 2 Platform, Standard Edition,
    +     * v 1.3.
    +     */
    +    RELEASE_3(47),
    +
    +    /**
    +     * The version recognized by the Java 2 Platform, Standard Edition,
    +     * v 1.4.
    +     */
    +    RELEASE_4(48),
    +
    +    /**
    +     * The version recognized by the Java 2 Platform, Standard
    +     * Edition 5.0.
    +     *
    +     * @see <a
    +     * href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index.html">
    +     * <cite>The Java Virtual Machine Specification, Second Edition updated for Java SE 5.0</cite></a>
    +     * @see <a href="https://jcp.org/en/jsr/detail?id=14">
    +     * JSR 14: Add Generic Types To The Java&trade; Programming Language</a>
    +     * @see <a href="https://jcp.org/en/jsr/detail?id=175">
    +     * JSR 175: A Metadata Facility for the Java&trade; Programming Language</a>
    +     */
    +    RELEASE_5(49),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 6.
    +     *
    +     * @see <a
    +     * href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index2.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE, Second Edition updated for Java SE 6</cite></a>
    +     */
    +    RELEASE_6(50),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 7.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se7/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 7 Edition</cite></a>
    +     */
    +    RELEASE_7(51),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 8.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se8/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 8 Edition</cite></a>
    +     * @see <a href="https://jcp.org/en/jsr/detail?id=335">
    +     * JSR 335: Lambda Expressions for the Java&trade; Programming Language</a>
    +     */
    +    RELEASE_8(52),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 9.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se9/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 9 Edition</cite></a>
    +     * @see <a href="https://jcp.org/en/jsr/detail?id=376">
    +     * JSR 376: Java&trade; Platform Module System</a>
    +     */
    +     RELEASE_9(53),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 10.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se10/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 10 Edition</cite></a>
    +     */
    +    RELEASE_10(54),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 11.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se11/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 11 Edition</cite></a>
    +     * @see <a href="https://openjdk.java.net/jeps/181">
    +     * JEP 181: Nest-Based Access Control</a>
    +     */
    +    RELEASE_11(55),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 12.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se12/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 12 Edition</cite></a>
    +     */
    +    RELEASE_12(56),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 13.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se13/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 13 Edition</cite></a>
    +     */
    +    RELEASE_13(57),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 14.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se14/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 14 Edition</cite></a>
    +     */
    +    RELEASE_14(58),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 15.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se15/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 15 Edition</cite></a>
    +     * @see <a href="https://openjdk.java.net/jeps/371">
    +     * JEP 371: Hidden Classes</a>
    +     */
    +    RELEASE_15(59),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 16.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se16/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 16 Edition</cite></a>
    +     */
    +    RELEASE_16(60),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 17.
    +     *
    +     * Additions in this release include sealed classes and
    +     * restoration of always-strict floating-point semantics.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se17/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 17 Edition</cite></a>
    +     * @see <a href="https://openjdk.java.net/jeps/306">
    +     * JEP 306: Restore Always-Strict Floating-Point Semantics</a>
    +     * @see <a href="https://openjdk.java.net/jeps/409">
    +     * JEP 409: Sealed Classes</a>
    +     */
    +    RELEASE_17(61),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 18.
    +     *
    +     * @see <a
    +     * href="https://docs.oracle.com/javase/specs/jvms/se18/html/index.html">
    +     * <cite>The Java Virtual Machine Specification, Java SE 18 Edition</cite></a>
    +     */
    +    RELEASE_18(62),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 19.
    +     */
    +    RELEASE_19(63),
    +
    +    /**
    +     * The version recognized by the Java Platform, Standard Edition
    +     * 20.
    +     */
    +    RELEASE_20(64);
    +
    +    private int major;
    +
    +    private ClassFileFormatVersion(int major) {
    +        this.major = major;
    +    }
    +
    +    /**
    +     * {@return the latest class file format version}
    +     */
    +    public static ClassFileFormatVersion latest() {
    +        return RELEASE_20;
    +    }
    +
    +    /**
    +     * {@return the major class file version as an integer}
    +     * @jvms 4.1 The {@code ClassFile} Structure
    +     */
    +    public int major() {
    +        return major;
    +    }
    +
    +    /**
    +     * {@return the latest class file format version that is usable
    +     * under the runtime version argument} If the runtime version's
    +     * {@linkplain Runtime.Version#feature() feature} is greater than
    +     * the feature of the {@linkplain #runtimeVersion() runtime
    +     * version} of the {@linkplain #latest() latest class file format
    +     * version}, an {@code IllegalArgumentException} is thrown.
    +     *
    +     * <p>Because the class file format versions of the Java platform
    +     * have so far followed a linear progression, only the feature
    +     * component of a runtime version is queried to determine the
    +     * mapping to a class file format version. If that linearity
    +     * changes in the future, other components of the runtime version
    +     * may influence the result.
    +     *
    +     * @apiNote
    +     * An expression to convert from a string value, for example
    +     * {@code "17"}, to the corresponding class file format version,
    +     * {@code RELEASE_17}, is:
    +     *
    +     * {@snippet lang="java" :
    +     * ClassFileFormatVersion.valueOf(Runtime.Version.parse("17"))}
    +     *
    +     * @param rv runtime version to map to a class file format version
    +     * @throws IllegalArgumentException if the feature of version
    +     * argument is greater than the feature of the platform version.
    +     */
    +    public static ClassFileFormatVersion valueOf(Runtime.Version rv) {
    +        // Could also implement this as a switch where a case was
    +        // added with each new release.
    +        return valueOf("RELEASE_" + rv.feature());
    +    }
    +
    +    /**
    +     * {@return the least runtime version that supports this class
    +     * file format version; otherwise {@code null}} The returned
    +     * runtime version has a {@linkplain Runtime.Version#feature()
    +     * feature} large enough to support this class file format version
    +     * and has no other elements set.
    +     *
    +     * Class file format versions greater than or equal to {@link
    +     * RELEASE_6} have non-{@code null} results.
    +     */
    +    public Runtime.Version runtimeVersion() {
    +        // Starting with Java SE 6, the leading digit was the primary
    +        // way of identifying the platform version.
    +        if (this.compareTo(RELEASE_6) >= 0) {
    +            return Runtime.Version.parse(Integer.toString(ordinal()));
    +        } else {
    +            return null;
    +        }
    +    }
    +
    +    /**
    +     * {@return the latest class file format version whose major class
    +     * file version matches the argument}
    +     * @param major the major class file version as an integer
    +     * @throws IllegalArgumentException if the argument is outside of
    +     * the range of major class file versions
    +     */
    +    public static ClassFileFormatVersion fromMajor(int major) {
    +        if (major < 45  // RELEASE_0.major()
    +            || major > latest().major()) {
    +            throw new IllegalArgumentException("Out of range major class file vesion "
    +                                               + major);
    +        }
    +        // RELEASE_0 and RELEASE_1 both have a major version of 45;
    +        // return RELEASE_1 for an argument of 45.
    +        return values()[major-44];
    +    }
    +}


Comments
Moving to Approved.
08-08-2022