< prev index next >

src/java.base/share/classes/java/lang/reflect/AccessFlag.java

Print this page

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.reflect;
 27 



 28 import java.lang.classfile.ClassModel;
 29 import java.lang.classfile.FieldModel;
 30 import java.lang.classfile.MethodModel;
 31 import java.lang.classfile.attribute.InnerClassInfo;
 32 import java.lang.classfile.attribute.MethodParameterInfo;
 33 import java.lang.classfile.attribute.ModuleAttribute;
 34 import java.lang.classfile.attribute.ModuleExportInfo;
 35 import java.lang.classfile.attribute.ModuleOpenInfo;
 36 import java.lang.classfile.attribute.ModuleRequireInfo;
 37 import java.lang.module.ModuleDescriptor;
 38 import java.util.AbstractSet;
 39 import java.util.Collection;
 40 import java.util.Iterator;
 41 import java.util.List;
 42 import java.util.Map;
 43 import java.util.NoSuchElementException;
 44 import java.util.Objects;
 45 import java.util.Set;
 46 import java.util.function.Consumer;
 47 import java.util.function.Predicate;

145     STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
146            List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
147 
148     /**
149      * The access flag {@code ACC_FINAL}, corresponding to the source
150      * modifier {@link Modifier#FINAL final}, with a mask
151      * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
152      */
153     FINAL(Modifier.FINAL, true,
154           Location.SET_FINAL_8,
155           List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
156                   Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
157 
158     /**
159      * The access flag {@code ACC_SUPER} with a mask value of {@code
160      * 0x0020}.
161      *
162      * @apiNote
163      * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
164      * flag as set in every class file (JVMS {@jvms 4.1}).














165      */
166     SUPER(0x0000_0020, false, Location.SET_CLASS, List.of()),



167 
168     /**
169      * The module flag {@code ACC_OPEN} with a mask value of {@code
170      * 0x0020}.
171      * @see java.lang.module.ModuleDescriptor#isOpen
172      */
173     OPEN(0x0000_0020, false, Location.SET_MODULE,
174          List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
175 
176     /**
177      * The module requires flag {@code ACC_TRANSITIVE} with a mask
178      * value of {@code 0x0020}.
179      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
180      */
181     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
182                List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
183 
184     /**
185      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
186      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with

247      * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
248      */
249     ABSTRACT(Modifier.ABSTRACT, true,
250              Location.SET_CLASS_METHOD_INNER_CLASS,
251              List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
252 
253     /**
254      * The access flag {@code ACC_STRICT}, corresponding to the source
255      * modifier {@link Modifier#STRICT strictfp}, with a mask value of
256      * <code>{@value "0x%04x" Modifier#STRICT}</code>.
257      *
258      * @apiNote
259      * The {@code ACC_STRICT} access flag is defined for class file
260      * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
261      * corresponding to Java SE 1.2 through 16.
262      */
263     STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
264            List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
265                    Map.entry(RELEASE_1, Location.EMPTY_SET))),
266 












267     /**
268      * The access flag {@code ACC_SYNTHETIC} with a mask value of
269      * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
270      * @see Class#isSynthetic()
271      * @see Executable#isSynthetic()
272      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
273      */
274     SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
275               List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
276                       Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
277                       Map.entry(RELEASE_4, Location.EMPTY_SET))),
278 
279     /**
280      * The access flag {@code ACC_ANNOTATION} with a mask value of
281      * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
282      * @see Class#isAnnotation()
283      */
284     ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
285                List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
286 

360      * {@return locations this flag can be applied to in the given class file
361      * format version}
362      * <p>
363      * This method returns an empty set if this flag is not defined in
364      * the given {@code cffv}.
365      *
366      * @param cffv the class file format version to use
367      * @throws NullPointerException if the parameter is {@code null}
368      */
369     public Set<Location> locations(ClassFileFormatVersion cffv) {
370         return Location.findInHistory(locations, historicalLocations, cffv);
371     }
372 
373     /**
374      * {@return an unmodifiable set of access flags for the given mask value
375      * appropriate for the location in question}
376      *
377      * @param mask bit mask of access flags
378      * @param location context to interpret mask value
379      * @throws IllegalArgumentException if the mask contains bit
380      * positions not support for the location in question
381      */
382     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
383         var definition = findDefinition(location);
384         int flagsMask = location.flagsMask();
385         int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
386         int unmatchedMask = mask & (~parsingMask);
387         if (unmatchedMask != 0) {
388             throw new IllegalArgumentException("Unmatched bit position 0x" +
389                     Integer.toHexString(unmatchedMask) +
390                     " for location " + location);
391         }
392         return new AccessFlagSet(definition, mask);
393     }
394 


























395     /**
396      * A location within a {@code class} file where flags can be applied.
397      * <p>
398      * Note that since these locations represent {@code class} file structures
399      * rather than language structures, many language structures, such
400      * as constructors and interfaces, are <em>not</em> present.
401      * @since 20
402      */
403     public enum Location {
404         /**
405          * Class location.
406          *
407          * @see Class#accessFlags()
408          * @see ClassModel#flags()
409          * @see Modifier#classModifiers()
410          * @see Modifier#interfaceModifiers()
411          * @jvms 4.1 The {@code ClassFile} Structure
412          */
413         CLASS(ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
414               ACC_INTERFACE | ACC_ABSTRACT |
415               ACC_SYNTHETIC | ACC_ANNOTATION |
416               ACC_ENUM | ACC_MODULE,
417               List.of(Map.entry(RELEASE_8, // no module
418                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
419                                 ACC_INTERFACE | ACC_ABSTRACT |
420                                 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
421                       Map.entry(RELEASE_4, // no synthetic, annotation, enum
422                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
423                                 ACC_INTERFACE | ACC_ABSTRACT))),
424 
425         /**
426          * Field location.
427          *
428          * @see Field#accessFlags()
429          * @see FieldModel#flags()
430          * @see Modifier#fieldModifiers()
431          * @jvms 4.5 Fields
432          */
433         FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
434               ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
435               ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM,
436               List.of(Map.entry(RELEASE_4, // no synthetic, enum
437                                 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
438                                 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
439                                 ACC_TRANSIENT))),
440 
441         /**
442          * Method location.
443          *
444          * @see Executable#accessFlags()
445          * @see MethodModel#flags()
446          * @see Modifier#methodModifiers()
447          * @see Modifier#constructorModifiers()
448          * @jvms 4.6 Methods
449          */
450         METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
451                ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
452                ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
453                ACC_ABSTRACT | ACC_SYNTHETIC,
454                List.of(Map.entry(RELEASE_16, // had strict
455                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |

457                                  ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
458                                  ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
459                        Map.entry(RELEASE_4, // no bridge, varargs, synthetic
460                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
461                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
462                                  ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
463                        Map.entry(RELEASE_1, // no strict
464                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
465                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
466                                  ACC_NATIVE | ACC_ABSTRACT))),
467 
468         /**
469          * Inner class location.
470          *
471          * @see Class#accessFlags()
472          * @see InnerClassInfo#flags()
473          * @see Modifier#classModifiers()
474          * @see Modifier#interfaceModifiers()
475          * @jvms 4.7.6 The {@code InnerClasses} Attribute
476          */
477         INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
478                     ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
479                     ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
480                     List.of(Map.entry(RELEASE_4, // no synthetic, annotation, enum
481                             ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
482                             ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
483                             ACC_ABSTRACT),
484                             Map.entry(RELEASE_0, 0))), // did not exist
485 
486         /**
487          * Method parameter location.
488          *
489          * @see Parameter#accessFlags()
490          * @see MethodParameterInfo#flags()
491          * @see Modifier#parameterModifiers()
492          * @jvms 4.7.24 The {@code MethodParameters} Attribute
493          */
494         METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
495                          List.of(Map.entry(RELEASE_7, 0))),  // did not exist
496 
497         /**

673          * @throws NullPointerException if {@code cffv} is {@code null}
674          * @since 25
675          */
676         public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
677             // implicit null check cffv
678             return new AccessFlagSet(findDefinition(this), flagsMask(cffv));
679         }
680     }
681 
682     private static AccessFlag[] createDefinition(AccessFlag... known) {
683         var ret = new AccessFlag[Character.SIZE];
684         for (var flag : known) {
685             var mask = flag.mask;
686             int pos = Integer.numberOfTrailingZeros(mask);
687             assert ret[pos] == null : ret[pos] + " " + flag;
688             ret[pos] = flag;
689         }
690         return ret;
691     }
692 
693     // Will take extra args in the future for valhalla switch
694     private static AccessFlag[] findDefinition(Location location) {
695         return switch (location) {
696             case CLASS -> CLASS_FLAGS;
697             case FIELD -> FIELD_FLAGS;
698             case METHOD -> METHOD_FLAGS;
699             case INNER_CLASS -> INNER_CLASS_FLAGS;
700             case METHOD_PARAMETER -> METHOD_PARAMETER_FLAGS;
701             case MODULE -> MODULE_FLAGS;
702             case MODULE_REQUIRES -> MODULE_REQUIRES_FLAGS;
703             case MODULE_EXPORTS -> MODULE_EXPORTS_FLAGS;
704             case MODULE_OPENS -> MODULE_OPENS_FLAGS;
705         };
706     }
707 
708     private static final @Stable AccessFlag[] // Can use stable array and lazy init in the future
709             CLASS_FLAGS = createDefinition(PUBLIC, FINAL, SUPER, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
710             FIELD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM),


711             METHOD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, BRIDGE, VARARGS, NATIVE, ABSTRACT, STRICT, SYNTHETIC),
712             INNER_CLASS_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),
713             METHOD_PARAMETER_FLAGS = createDefinition(FINAL, SYNTHETIC, MANDATED),
714             MODULE_FLAGS = createDefinition(OPEN, SYNTHETIC, MANDATED),
715             MODULE_REQUIRES_FLAGS = createDefinition(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED),
716             MODULE_EXPORTS_FLAGS = createDefinition(SYNTHETIC, MANDATED),
717             MODULE_OPENS_FLAGS = createDefinition(SYNTHETIC, MANDATED);
718 
719     private static int undefinedMask(AccessFlag[] definition, int mask) {
720         assert definition.length == Character.SIZE;
721         int definedMask = 0;
722         for (int i = 0; i < Character.SIZE; i++) {
723             if (definition[i] != null) {
724                 definedMask |= 1 << i;
725             }
726         }
727         return mask & ~definedMask;
728     }
729 
730     private static final class AccessFlagSet extends AbstractSet<AccessFlag> {
731         private final @Stable AccessFlag[] definition;
732         private final int mask;

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.reflect;
 27 
 28 import jdk.internal.javac.PreviewFeature;
 29 import jdk.internal.misc.PreviewFeatures;
 30 
 31 import java.lang.classfile.ClassModel;
 32 import java.lang.classfile.FieldModel;
 33 import java.lang.classfile.MethodModel;
 34 import java.lang.classfile.attribute.InnerClassInfo;
 35 import java.lang.classfile.attribute.MethodParameterInfo;
 36 import java.lang.classfile.attribute.ModuleAttribute;
 37 import java.lang.classfile.attribute.ModuleExportInfo;
 38 import java.lang.classfile.attribute.ModuleOpenInfo;
 39 import java.lang.classfile.attribute.ModuleRequireInfo;
 40 import java.lang.module.ModuleDescriptor;
 41 import java.util.AbstractSet;
 42 import java.util.Collection;
 43 import java.util.Iterator;
 44 import java.util.List;
 45 import java.util.Map;
 46 import java.util.NoSuchElementException;
 47 import java.util.Objects;
 48 import java.util.Set;
 49 import java.util.function.Consumer;
 50 import java.util.function.Predicate;

148     STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
149            List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
150 
151     /**
152      * The access flag {@code ACC_FINAL}, corresponding to the source
153      * modifier {@link Modifier#FINAL final}, with a mask
154      * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
155      */
156     FINAL(Modifier.FINAL, true,
157           Location.SET_FINAL_8,
158           List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
159                   Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
160 
161     /**
162      * The access flag {@code ACC_SUPER} with a mask value of {@code
163      * 0x0020}.
164      *
165      * @apiNote
166      * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
167      * flag as set in every class file (JVMS {@jvms 4.1}).
168      * If preview feature is enabled,
169      * the {@code 0x0020} access flag bit is {@linkplain #IDENTITY IDENTITY access flag}.
170      */
171     SUPER(0x0000_0020, false,
172           PreviewFeatures.isEnabled() ? Location.EMPTY_SET : Location.SET_CLASS,
173           List.of()),
174 
175     /**
176      * The access flag {@code ACC_IDENTITY}, corresponding to the
177      * modifier {@link Modifier#IDENTITY identity}, with a mask
178      * value of <code>{@value "0x%04x" Modifier#IDENTITY}</code>.
179      * @jvms 4.1 -B. Class access and property modifiers
180      *
181      * @since Valhalla
182      */
183     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
184     IDENTITY(Modifier.IDENTITY, false,
185             PreviewFeatures.isEnabled() ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET,
186             List.of()),
187 
188     /**
189      * The module flag {@code ACC_OPEN} with a mask value of {@code
190      * 0x0020}.
191      * @see java.lang.module.ModuleDescriptor#isOpen
192      */
193     OPEN(0x0000_0020, false, Location.SET_MODULE,
194          List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
195 
196     /**
197      * The module requires flag {@code ACC_TRANSITIVE} with a mask
198      * value of {@code 0x0020}.
199      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
200      */
201     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
202                List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
203 
204     /**
205      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
206      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with

267      * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
268      */
269     ABSTRACT(Modifier.ABSTRACT, true,
270              Location.SET_CLASS_METHOD_INNER_CLASS,
271              List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
272 
273     /**
274      * The access flag {@code ACC_STRICT}, corresponding to the source
275      * modifier {@link Modifier#STRICT strictfp}, with a mask value of
276      * <code>{@value "0x%04x" Modifier#STRICT}</code>.
277      *
278      * @apiNote
279      * The {@code ACC_STRICT} access flag is defined for class file
280      * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
281      * corresponding to Java SE 1.2 through 16.
282      */
283     STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
284            List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
285                    Map.entry(RELEASE_1, Location.EMPTY_SET))),
286 
287     /**
288      * The access flag {@code ACC_STRICT_INIT}, with a mask
289      * value of {@code 0x0800}.
290      *
291      * @jvms 4.5 Fields
292      * @since Valhalla
293      */
294     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
295     STRICT_INIT(Modifier.STRICT, false,
296             PreviewFeatures.isEnabled() ? Location.SET_FIELD : Location.EMPTY_SET,
297                 List.of()),
298 
299     /**
300      * The access flag {@code ACC_SYNTHETIC} with a mask value of
301      * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
302      * @see Class#isSynthetic()
303      * @see Executable#isSynthetic()
304      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
305      */
306     SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
307               List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
308                       Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
309                       Map.entry(RELEASE_4, Location.EMPTY_SET))),
310 
311     /**
312      * The access flag {@code ACC_ANNOTATION} with a mask value of
313      * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
314      * @see Class#isAnnotation()
315      */
316     ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
317                List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
318 

392      * {@return locations this flag can be applied to in the given class file
393      * format version}
394      * <p>
395      * This method returns an empty set if this flag is not defined in
396      * the given {@code cffv}.
397      *
398      * @param cffv the class file format version to use
399      * @throws NullPointerException if the parameter is {@code null}
400      */
401     public Set<Location> locations(ClassFileFormatVersion cffv) {
402         return Location.findInHistory(locations, historicalLocations, cffv);
403     }
404 
405     /**
406      * {@return an unmodifiable set of access flags for the given mask value
407      * appropriate for the location in question}
408      *
409      * @param mask bit mask of access flags
410      * @param location context to interpret mask value
411      * @throws IllegalArgumentException if the mask contains bit
412      * positions not supported for the location in question
413      */
414     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
415         var definition = findDefinition(location);
416         int flagsMask = location.flagsMask();
417         int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
418         int unmatchedMask = mask & (~parsingMask);
419         if (unmatchedMask != 0) {
420             throw new IllegalArgumentException("Unmatched bit position 0x" +
421                     Integer.toHexString(unmatchedMask) +
422                     " for location " + location);
423         }
424         return new AccessFlagSet(definition, mask);
425     }
426 
427     /**
428      * {@return an unmodifiable set of access flags for the given mask value
429      * appropriate for the location in question}
430      *
431      * @param mask bit mask of access flags
432      * @param location context to interpret mask value
433      * @param cffv the class file format version
434      * @throws IllegalArgumentException if the mask contains bit
435      * positions not supported for the location in question
436      *
437      * @since Valhalla
438      */
439     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
440                                                     ClassFileFormatVersion cffv) {
441         var definition = findDefinition(location);
442         int flagsMask = location.flagsMask(cffv);
443         int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
444         int unmatchedMask = mask & (~parsingMask);
445         if (unmatchedMask != 0) {
446             throw new IllegalArgumentException("Unmatched bit position 0x" +
447                     Integer.toHexString(unmatchedMask) +
448                     " for location " + location);
449         }
450         return new AccessFlagSet(definition, mask);
451     }
452 
453     /**
454      * A location within a {@code class} file where flags can be applied.
455      * <p>
456      * Note that since these locations represent {@code class} file structures
457      * rather than language structures, many language structures, such
458      * as constructors and interfaces, are <em>not</em> present.
459      * @since 20
460      */
461     public enum Location {
462         /**
463          * Class location.
464          *
465          * @see Class#accessFlags()
466          * @see ClassModel#flags()
467          * @see Modifier#classModifiers()
468          * @see Modifier#interfaceModifiers()
469          * @jvms 4.1 The {@code ClassFile} Structure
470          */
471         CLASS(ACC_PUBLIC | ACC_FINAL | (PreviewFeatures.isEnabled() ? ACC_IDENTITY : ACC_SUPER) |
472               ACC_INTERFACE | ACC_ABSTRACT |
473               ACC_SYNTHETIC | ACC_ANNOTATION |
474               ACC_ENUM | ACC_MODULE,
475               List.of(Map.entry(RELEASE_8, // no module
476                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
477                                 ACC_INTERFACE | ACC_ABSTRACT |
478                                 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
479                       Map.entry(RELEASE_4, // no synthetic, annotation, enum
480                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
481                                 ACC_INTERFACE | ACC_ABSTRACT))),
482 
483         /**
484          * Field location.
485          *
486          * @see Field#accessFlags()
487          * @see FieldModel#flags()
488          * @see Modifier#fieldModifiers()
489          * @jvms 4.5 Fields
490          */
491         FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
492               ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
493               ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | (PreviewFeatures.isEnabled() ? ACC_STRICT : 0),
494               List.of(Map.entry(RELEASE_4, // no synthetic, enum
495                                 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
496                                 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
497                                 ACC_TRANSIENT))),
498 
499         /**
500          * Method location.
501          *
502          * @see Executable#accessFlags()
503          * @see MethodModel#flags()
504          * @see Modifier#methodModifiers()
505          * @see Modifier#constructorModifiers()
506          * @jvms 4.6 Methods
507          */
508         METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
509                ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
510                ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
511                ACC_ABSTRACT | ACC_SYNTHETIC,
512                List.of(Map.entry(RELEASE_16, // had strict
513                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |

515                                  ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
516                                  ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
517                        Map.entry(RELEASE_4, // no bridge, varargs, synthetic
518                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
519                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
520                                  ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
521                        Map.entry(RELEASE_1, // no strict
522                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
523                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
524                                  ACC_NATIVE | ACC_ABSTRACT))),
525 
526         /**
527          * Inner class location.
528          *
529          * @see Class#accessFlags()
530          * @see InnerClassInfo#flags()
531          * @see Modifier#classModifiers()
532          * @see Modifier#interfaceModifiers()
533          * @jvms 4.7.6 The {@code InnerClasses} Attribute
534          */
535         INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | (PreviewFeatures.isEnabled() ? ACC_IDENTITY : 0) |
536                     ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
537                     ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
538                     List.of(Map.entry(RELEASE_4, // no synthetic, annotation, enum
539                             ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
540                             ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
541                             ACC_ABSTRACT),
542                             Map.entry(RELEASE_0, 0))), // did not exist
543 
544         /**
545          * Method parameter location.
546          *
547          * @see Parameter#accessFlags()
548          * @see MethodParameterInfo#flags()
549          * @see Modifier#parameterModifiers()
550          * @jvms 4.7.24 The {@code MethodParameters} Attribute
551          */
552         METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
553                          List.of(Map.entry(RELEASE_7, 0))),  // did not exist
554 
555         /**

731          * @throws NullPointerException if {@code cffv} is {@code null}
732          * @since 25
733          */
734         public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
735             // implicit null check cffv
736             return new AccessFlagSet(findDefinition(this), flagsMask(cffv));
737         }
738     }
739 
740     private static AccessFlag[] createDefinition(AccessFlag... known) {
741         var ret = new AccessFlag[Character.SIZE];
742         for (var flag : known) {
743             var mask = flag.mask;
744             int pos = Integer.numberOfTrailingZeros(mask);
745             assert ret[pos] == null : ret[pos] + " " + flag;
746             ret[pos] = flag;
747         }
748         return ret;
749     }
750 

751     private static AccessFlag[] findDefinition(Location location) {
752         return switch (location) {
753             case CLASS -> CLASS_FLAGS;
754             case FIELD -> FIELD_FLAGS;
755             case METHOD -> METHOD_FLAGS;
756             case INNER_CLASS -> INNER_CLASS_FLAGS;
757             case METHOD_PARAMETER -> METHOD_PARAMETER_FLAGS;
758             case MODULE -> MODULE_FLAGS;
759             case MODULE_REQUIRES -> MODULE_REQUIRES_FLAGS;
760             case MODULE_EXPORTS -> MODULE_EXPORTS_FLAGS;
761             case MODULE_OPENS -> MODULE_OPENS_FLAGS;
762         };
763     }
764 
765     private static final @Stable AccessFlag[] // Can use stable array and lazy init in the future
766             CLASS_FLAGS = createDefinition(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
767               FIELD_FLAGS = PreviewFeatures.isEnabled() ? // Using Valhalla
768               createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT) :
769               createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM),
770             METHOD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, BRIDGE, VARARGS, NATIVE, ABSTRACT, STRICT, SYNTHETIC),
771             INNER_CLASS_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),
772             METHOD_PARAMETER_FLAGS = createDefinition(FINAL, SYNTHETIC, MANDATED),
773             MODULE_FLAGS = createDefinition(OPEN, SYNTHETIC, MANDATED),
774             MODULE_REQUIRES_FLAGS = createDefinition(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED),
775             MODULE_EXPORTS_FLAGS = createDefinition(SYNTHETIC, MANDATED),
776             MODULE_OPENS_FLAGS = createDefinition(SYNTHETIC, MANDATED);
777 
778     private static int undefinedMask(AccessFlag[] definition, int mask) {
779         assert definition.length == Character.SIZE;
780         int definedMask = 0;
781         for (int i = 0; i < Character.SIZE; i++) {
782             if (definition[i] != null) {
783                 definedMask |= 1 << i;
784             }
785         }
786         return mask & ~definedMask;
787     }
788 
789     private static final class AccessFlagSet extends AbstractSet<AccessFlag> {
790         private final @Stable AccessFlag[] definition;
791         private final int mask;
< prev index next >