JDK-8297741 : AccessFlags should be specific to class file version
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Priority: P3
  • Status: Draft
  • Resolution: Unresolved
  • Fix Versions: 20
  • Submitted: 2022-11-28
  • Updated: 2022-12-05
Related Reports
CSR :  
Description
Summary
-------

The AccessFlags for classes, methods, constructors and fields should reflect the access flags specified for the class file format version.

Problem
-------

The `accessFlags()` methods added (in JDK 20, the current release) to java.lang.Class, java.lang.reflect.Executable, and java.lang.reflect.Field are silent about the dependency of the access flags on the class file format version. 
For current and past class file format versions there are few significant variations but future changes are anticipated that change the meaning of some access flag mask bits. One example is the STRICTFP access flag that only applies to releases 2 through 16.

Solution
--------

The `accessFlags()` methods should mention that the access flags returned are those applicable to the class file format version of the class.
The existing `AccessFlag.Locations` API already contains information about the locations that are applicable to a class file format version.
That information should be used to construct the set of AccessFlags returned.
A method is added to `AccessFlag` that returns the applicable flags for a particular mask, Location, and class file format version:

    Set<AccessFlags> maskToAccessFlags(int mask, Location, ClassFileFormatVersion cffv)

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

java.lang.Class addition to the javadoc of `accessFlags()`:

    @@ -1332,6 +1333,9 @@ public final class Class<T> implements java.io.Serializable,
     /**
      * {@return an unmodifiable set of the {@linkplain AccessFlag access
      * flags} for this class, possibly empty}
    + * The {@code AccessFlags} may depend on the class file format version of the class.
      *
      * <p> If the underlying class is an array class:
      * <ul>
    @@ -1340,6 +1344,7 @@ public final class Class<T> implements java.io.Serializable,
      * <li> its {@code ABSTRACT} and {@code FINAL} flags are present
      * <li> its {@code INTERFACE} flag is absent, even when the
      *      component type is an interface
    + * <li> its class file format version is that of the component class
      * </ul>
      ...
      */
     public Set<AccessFlag> accessFlags() {...}

java.lang.reflect.Executable additions to `accessFlags()`, this is inherited by Constructor and Method classes:

      @@ -213,6 +213,9 @@ public abstract sealed class Executable extends AccessibleObject
    /**
      * {@return an unmodifiable set of the {@linkplain AccessFlag
      * access flags} for the executable represented by this object,
      * possibly empty}
    + * The {@code AccessFlags} may depend on the class file format version of the class.
      ...
      */
     public Set<AccessFlag> accessFlags() {...}

java.lang.reflect.Field addition to method `accessFlag()`:

         /**
      * {@return an unmodifiable set of the {@linkplain AccessFlag
      * access flags} for this field, possibly empty}
    + * The {@code AccessFlags} may depend on the class file format version of the class.
      ...
      */
      public Set<AccessFlag> accessFlags() {...}

java.lang.reflect.AccessFlag additional method:

    + /**
    +  * {@return an unmodifiable set of access flags for the given mask value
    +  * appropriate for the class file format version and location}
    +  *
    +  * @param mask bit mask of access flags
    +  * @param location context to interpret mask value
    +  * @param cffv the class file format version
    +  */
    + public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
    +                                                    ClassFileFormatVersion cffv) {... }