JDK-8347626 : Provide valid flags and mask in AccessFlag.Location
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 25
  • Submitted: 2025-01-13
  • Updated: 2025-04-29
  • Resolved: 2025-04-29
Related Reports
CSR :  
Relates :  
Relates :  
Description
Summary
-------

Add new accessor methods to `AccessFlag.Location` and correct the historical locations reported by `AccessFlag.SYNTHETIC`.

Problem
-------

1. In the ClassFile API and other locations, we often mention about IllegalArgumentException caused by the mismatch of masks for access flags, but we never provided a way to easily detect if a mask has mismatch.
2. We cannot easily get the `AccessFlag` for a location; it's easy the other way around.
3. `ACC_SYNTHETIC` was added in Java SE Platform 5.0, but current `AccessFlag.SYNTHETIC` behaves as if it was only added in 7. Keeping this inconsistent behavior increases the implementation complexity of the new methods.

Solution
--------

1. Add these new methods to `AccessFlag.Location`: 
- `int flagsMask()`
- `int flagsMask(ClassFileFormatVersion)`
- `Set<AccessFlag> flags()`
- `Set<AccessFlag> flags(ClassFileFormatVersion)`

2. Change the behavior of `AccessFlag.SYNTHETIC` to apply to all of classes, inner classes, methods, and fields from releases 5.0 to 7, to ensure consistency between `AccessFlag` and `AccessFlag.Location`.

3. Document that historical locations may return empty if the flag does not exist, and the no-CFFV version is for the current version, which is more accurate than "latest".

4. Reimplement maskToAccessFlags withe the location-based information, making it align with the immutable collections in this process (UOE, null hostility)

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

```
@@ -425,31 +307,31 @@ public Set<Location> apply(ClassFileFormatVersion cffv) {
     /**
-     * {@return the corresponding integer mask for the access flag}
+     * {@return the corresponding mask for the access flag}  The mask has
+     * exactly one bit set and is in the range of {@code char}.
      */
     public int mask() {
     }
 
     /**
-     * {@return whether or not the flag has a directly corresponding
+     * {@return whether or not this flag has a directly corresponding
      * modifier in the Java programming language}
      */
     public boolean sourceModifier() {
@@ -458,7 +339,7 @@ public boolean sourceModifier() {
 
     /**
-     * {@return kinds of constructs the flag can be applied to in the
-     * latest class file format version}
+     * {@return locations this flag can be applied to in the current class file
+     * format version}
+     * <p>
+     * This method returns an empty set if this flag is not defined in
+     * the current class file format version.
      */
     public Set<Location> locations() {
         return locations;
@@ -467,16 +348,15 @@ public Set<Location> locations() {
     /**
-     * {@return kinds of constructs the flag can be applied to in the
-     * given class file format version}
+     * {@return locations this flag can be applied to in the given class file
+     * format version}
+     * <p>
+     * This method returns an empty set if this flag is not defined in
+     * the given {@code cffv}.
+     *
      * @param cffv the class file format version to use
      * @throws NullPointerException if the parameter is {@code null}
      */
     public Set<Location> locations(ClassFileFormatVersion cffv) {
     }
 
     /**
@@ -516,57 +418,129 @@ public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
     public enum Location {
         /**
          * Class location.
-         * @jvms 4.1 The ClassFile Structure
+         *
+         * @see Class#accessFlags()
+         * @see ClassModel#flags()
+         * @jvms 4.1 The {@code ClassFile} Structure
          */
         CLASS,
 
         /**
          * Field location.
+         *
+         * @see Field#accessFlags()
+         * @see FieldModel#flags()
          * @jvms 4.5 Fields
          */
         FIELD,
 
         /**
          * Method location.
+         *
+         * @see Executable#accessFlags()
+         * @see MethodModel#flags()
          * @jvms 4.6 Methods
          */
         METHOD,
 
         /**
          * Inner class location.
-         * @jvms 4.7.6 The InnerClasses Attribute
+         *
+         * @see Class#accessFlags()
+         * @see InnerClassInfo#flags()
+         * @jvms 4.7.6 The {@code InnerClasses} Attribute
          */
         INNER_CLASS,
 
         /**
          * Method parameter location.
-         * @jvms 4.7.24 The MethodParameters Attribute
+         *
+         * @see Parameter#accessFlags()
+         * @see MethodParameterInfo#flags()
+         * @jvms 4.7.24 The {@code MethodParameters} Attribute
          */
         METHOD_PARAMETER,
 
         /**
-         * Module location
-         * @jvms 4.7.25 The Module Attribute
+         * Module location.
+         *
+         * @see ModuleDescriptor#accessFlags()
+         * @see ModuleAttribute#moduleFlags()
+         * @jvms 4.7.25 The {@code Module} Attribute
          */
         MODULE,
 
         /**
-         * Module requires location
-         * @jvms 4.7.25 The Module Attribute
+         * Module requires location.
+         *
+         * @see ModuleDescriptor.Requires#accessFlags()
+         * @see ModuleRequireInfo#requiresFlags()
+         * @jvms 4.7.25 The {@code Module} Attribute
          */
         MODULE_REQUIRES,

         /**
-         * Module exports location
-         * @jvms 4.7.25 The Module Attribute
+         * Module exports location.
+         *
+         * @see ModuleDescriptor.Exports#accessFlags()
+         * @see ModuleExportInfo#exportsFlags()
+         * @jvms 4.7.25 The {@code Module} Attribute
          */
         MODULE_EXPORTS,
 
         /**
-         * Module opens location
-         * @jvms 4.7.25 The Module Attribute
+         * Module opens location.
+         *
+         * @see ModuleDescriptor.Opens#accessFlags()
+         * @see ModuleOpenInfo#opensFlags()
+         * @jvms 4.7.25 The {@code Module} Attribute
          */
         MODULE_OPENS;
 
         // Repeated sets of locations used by AccessFlag constants
         private static final Set<Location> EMPTY_SET = Set.of();
@@ -618,37 +572,218 @@ public enum Location {
+
+        /**
+         * {@return the union of masks of all access flags defined for
+         * this location in the current class file format version}
+         * <p>
+         * This method returns {@code 0} if this location does not exist in
+         * the current class file format version.
+         *
+         * @since 25
+         */
+        public int flagsMask() {
+            return flagsMask;
+        }
+
+        /**
+         * {@return the union of masks of all access flags defined for
+         * this location in the given class file format version}
+         * <p>
+         * This method returns {@code 0} if this location does not exist in
+         * the given {@code cffv}.
+         *
+         * @param cffv the class file format version
+         * @throws NullPointerException if {@code cffv} is {@code null}
+         * @since 25
+         */
+        public int flagsMask(ClassFileFormatVersion cffv) {
+        }
+
+        /**
+         * {@return the set of access flags defined for this location in the
+         * current class file format version}  The set is immutable.
+         * <p>
+         * This method returns an empty set if this location does not exist
+         * in the current class file format version.
+         *
+         * @since 25
+         */
+        public Set<AccessFlag> flags() {
+        }
+
+        /**
+         * {@return the set of access flags defined for this location in the
+         * given class file format version}  The set is immutable.
+         * <p>
+         * This method returns an empty set if this location does not exist
+         * in the given {@code cffv}.
+         *
+         * @param cffv the class file format version
+         * @throws NullPointerException if {@code cffv} is {@code null}
+         * @since 25
+         */
+        public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
+        }
```
Comments
Moving revised request to Approved.
29-04-2025

I have removed the "preview" things. It will be addressed in a separate issue. Moving to proposed for review on the updated spec.
26-04-2025

Moving to Provisional, not Approved. [~liach], from text structuring point of view, I'd prefer if the "this is how things work in preview mode" paragraph appeared once at the type-level and then was referred to by a see or link tag in each affected method.
24-04-2025