JDK-8297741 : AccessFlag.maskToAccessFlags should be specific to class file version
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 25
  • Submitted: 2022-11-28
  • Updated: 2025-04-30
  • Resolved: 2025-04-30
Related Reports
CSR :  
Relates :  
Relates :  
Description
Summary
-------

AccessFlag.maskToAccessFlags should be able to reject access flags not present in a particular location in a particular version, and the `accessFlags()` methods for classes, methods, constructors, and fields should reflect the access flags specified for the class file format version of the original class file.

Problem
-------

The `accessFlags()` methods added in JDK 20 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`/`ACC_STRICT` 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)`

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

java.lang.reflect.AccessFlag now has two `maskToAccessFlags` methods:

```
/**
 * {@return an unmodifiable set of access flags for the given mask value
 * appropriate for the location in the current class file format version}
 *
 * @param mask bit mask of access flags
 * @param location context to interpret mask value
 * @throws IllegalArgumentException if the mask contains bit
 * positions not defined for the location in the current class file format
 * @throws NullPointerException if {@code location} is {@code null}
 */
public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {

/**
 * {@return an unmodifiable set of access flags for the given mask value
 * appropriate for the location in the given class file format version}
 *
 * @param mask bit mask of access flags
 * @param location context to interpret mask value
 * @param cffv the class file format to interpret mask value
 * @throws IllegalArgumentException if the mask contains bit
 * positions not defined for the location in the given class file format
 * @throws NullPointerException if {@code location} or {@code cffv} is {@code null}
 * @since 25
 */
public static Set<AccessFlag> maskToAccessFlags(int mask, Location location, ClassFileFormatVersion cffv) {
```

For the existing 2-arg version, return tag adds "in the current class file format version", "position not supported" becomes "positions not defined", and a missing clause for NPE is added.
Comments
Moving to Approved. Probably can get away without a release note for the behavioral change.
30-04-2025

Thanks for the suggestion. I have added "the current class file format version". The only difference is for parsing strictfp on methods.
26-04-2025

Moving to Provisional, not Approved. [~liach], before the CSR is Finalized, please include an update to the spec of maskToAccessFlags(int mask, AccessFlag.Location location) to discuss what (implicit) class file version is used. Something like "Returns an unmodifiable set of access flags for the given mask value appropriate for the location in question _in the latest class file version_." (This would be a change in behavior from what that method does now. Spec'ing the current behavior would be take more work.)
23-04-2025