1 /*
  2  * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  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 
 30 import java.lang.classfile.ClassModel;
 31 import java.lang.classfile.FieldModel;
 32 import java.lang.classfile.MethodModel;
 33 import java.lang.classfile.attribute.InnerClassInfo;
 34 import java.lang.classfile.attribute.MethodParameterInfo;
 35 import java.lang.classfile.attribute.ModuleAttribute;
 36 import java.lang.classfile.attribute.ModuleExportInfo;
 37 import java.lang.classfile.attribute.ModuleOpenInfo;
 38 import java.lang.classfile.attribute.ModuleRequireInfo;
 39 import java.lang.module.ModuleDescriptor;
 40 import java.util.AbstractSet;
 41 import java.util.Collection;
 42 import java.util.Iterator;
 43 import java.util.List;
 44 import java.util.Map;
 45 import java.util.NoSuchElementException;
 46 import java.util.Objects;
 47 import java.util.Set;
 48 import java.util.function.Consumer;
 49 import java.util.function.Predicate;
 50 
 51 import jdk.internal.vm.annotation.Stable;
 52 
 53 import static java.lang.classfile.ClassFile.*;
 54 import static java.lang.reflect.ClassFileFormatVersion.*;
 55 
 56 /**
 57  * Represents a JVM access or module-related flag on a runtime member,
 58  * such as a {@linkplain Class class}, {@linkplain Field field}, or
 59  * {@linkplain Executable method}.
 60  *
 61  * <P>JVM access and module-related flags are related to, but distinct
 62  * from Java language {@linkplain Modifier modifiers}. Some modifiers
 63  * and access flags have a one-to-one correspondence, such as {@code
 64  * public}. In other cases, some language-level modifiers do
 65  * <em>not</em> have an access flag, such as {@code sealed} (JVMS
 66  * {@jvms 4.7.31}) and some access flags have no corresponding
 67  * modifier, such as {@linkplain #SYNTHETIC synthetic}.
 68  *
 69  * <p>The values for the constants representing the access and module
 70  * flags are taken from sections of <cite>The Java Virtual Machine
 71  * Specification</cite> including {@jvms 4.1} (class access and
 72  * property modifiers), {@jvms 4.5} (field access and property flags),
 73  * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
 74  * (nested class access and property flags), {@jvms 4.7.24} (method
 75  * parameters), and {@jvms 4.7.25} (module flags and requires,
 76  * exports, and opens flags).
 77  *
 78  * <p>The {@linkplain #mask() mask} values for the different access
 79  * flags are <em>not</em> distinct. Flags are defined for different
 80  * kinds of JVM structures and the same bit position has different
 81  * meanings in different contexts. For example, {@code 0x0000_0040}
 82  * indicates a {@link #VOLATILE volatile} field but a {@linkplain
 83  * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
 84  * #TRANSIENT transient} field but a {@linkplain #VARARGS variable
 85  * arity (varargs)} method.
 86  *
 87  * @implSpec
 88  * The access flag constants are ordered by non-decreasing mask
 89  * value; that is the mask value of a constant is greater than or
 90  * equal to the mask value of an immediate neighbor to its (syntactic)
 91  * left. If new constants are added, this property will be
 92  * maintained. That implies new constants will not necessarily be
 93  * added at the end of the existing list.
 94  *
 95  * @apiNote
 96  * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new
 97  * {@linkplain Runtime.Version#feature() feature release}. A new class
 98  * file version may define new access flags or retire old ones. {@code
 99  * AccessFlag} is intended to model the set of access flags across
100  * class file format versions. The range of versions an access flag is
101  * recognized is not explicitly indicated in this API. See the current
102  * <cite>The Java Virtual Machine Specification</cite> for
103  * details. Unless otherwise indicated, access flags can be assumed to
104  * be recognized in the {@linkplain Runtime#version() current
105  * version}.
106  *
107  * @see java.lang.reflect.Modifier
108  * @see java.lang.module.ModuleDescriptor.Modifier
109  * @see java.lang.module.ModuleDescriptor.Requires.Modifier
110  * @see java.lang.module.ModuleDescriptor.Exports.Modifier
111  * @see java.lang.module.ModuleDescriptor.Opens.Modifier
112  * @see java.compiler/javax.lang.model.element.Modifier
113  * @since 20
114  */
115 @SuppressWarnings("doclint:reference") // cross-module link
116 public enum AccessFlag {
117     /**
118      * The access flag {@code ACC_PUBLIC}, corresponding to the source
119      * modifier {@link Modifier#PUBLIC public}, with a mask value of
120      * <code>{@value "0x%04x" Modifier#PUBLIC}</code>.
121      */
122     PUBLIC(Modifier.PUBLIC, true,
123            Location.SET_CLASS_FIELD_METHOD_INNER_CLASS,
124            List.of(Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
125 
126     /**
127      * The access flag {@code ACC_PRIVATE}, corresponding to the
128      * source modifier {@link Modifier#PRIVATE private}, with a mask
129      * value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>.
130      */
131     PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS,
132             List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
133 
134     /**
135      * The access flag {@code ACC_PROTECTED}, corresponding to the
136      * source modifier {@link Modifier#PROTECTED protected}, with a mask
137      * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>.
138      */
139     PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS,
140               List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
141 
142     /**
143      * The access flag {@code ACC_STATIC}, corresponding to the source
144      * modifier {@link Modifier#STATIC static}, with a mask value of
145      * <code>{@value "0x%04x" Modifier#STATIC}</code>.
146      */
147     STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
148            List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
149 
150     /**
151      * The access flag {@code ACC_FINAL}, corresponding to the source
152      * modifier {@link Modifier#FINAL final}, with a mask
153      * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
154      */
155     FINAL(Modifier.FINAL, true,
156           Location.SET_FINAL_8,
157           List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
158                   Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
159 
160     /**
161      * The access flag {@code ACC_SUPER} with a mask value of {@code
162      * 0x0020}.
163      *
164      * @apiNote
165      * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
166      * flag as set in every class file (JVMS {@jvms 4.1}).
167      * If preview feature is enabled,
168      * the {@code 0x0020} access flag bit is {@linkplain #IDENTITY IDENTITY access flag}.
169      */
170     SUPER(0x0000_0020, false,
171           Location.EMPTY_SET,
172           List.of(Map.entry(latest(), Location.SET_CLASS))),
173 
174     /**
175      * The access flag {@code ACC_IDENTITY}, corresponding to the
176      * modifier {@link Modifier#IDENTITY identity}, with a mask
177      * value of <code>{@value "0x%04x" Modifier#IDENTITY}</code>.
178      * @jvms 4.1 -B. Class access and property modifiers
179      *
180      * @since Valhalla
181      */
182     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
183     IDENTITY(Modifier.IDENTITY, false,
184              Location.SET_CLASS_INNER_CLASS,
185              List.of(Map.entry(latest(), Location.EMPTY_SET))),
186 
187     /**
188      * The module flag {@code ACC_OPEN} with a mask value of {@code
189      * 0x0020}.
190      * @see java.lang.module.ModuleDescriptor#isOpen
191      */
192     OPEN(0x0000_0020, false, Location.SET_MODULE,
193          List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
194 
195     /**
196      * The module requires flag {@code ACC_TRANSITIVE} with a mask
197      * value of {@code 0x0020}.
198      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
199      */
200     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
201                List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
202 
203     /**
204      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
205      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
206      * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
207      */
208     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, List.of()),
209 
210     /**
211      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
212      * value of {@code 0x0040}.
213      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
214      */
215     STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
216                  List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
217 
218     /**
219      * The access flag {@code ACC_VOLATILE}, corresponding to the
220      * source modifier {@link Modifier#VOLATILE volatile}, with a mask
221      * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
222      */
223     VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, List.of()),
224 
225     /**
226      * The access flag {@code ACC_BRIDGE} with a mask value of
227      * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
228      * @see Method#isBridge()
229      */
230     BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
231            List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
232 
233     /**
234      * The access flag {@code ACC_TRANSIENT}, corresponding to the
235      * source modifier {@link Modifier#TRANSIENT transient}, with a
236      * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>.
237      */
238     TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, List.of()),
239 
240     /**
241      * The access flag {@code ACC_VARARGS} with a mask value of
242      * <code>{@value "0x%04x" Modifier#VARARGS}</code>.
243      * @see Executable#isVarArgs()
244      */
245     VARARGS(Modifier.VARARGS, false, Location.SET_METHOD,
246             List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
247 
248     /**
249      * The access flag {@code ACC_NATIVE}, corresponding to the source
250      * modifier {@link Modifier#NATIVE native}, with a mask value of
251      * <code>{@value "0x%04x" Modifier#NATIVE}</code>.
252      */
253     NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, List.of()),
254 
255     /**
256      * The access flag {@code ACC_INTERFACE} with a mask value of
257      * {@code 0x0200}.
258      * @see Class#isInterface()
259      */
260     INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS,
261               List.of(Map.entry(RELEASE_0, Location.SET_CLASS))),
262 
263     /**
264      * The access flag {@code ACC_ABSTRACT}, corresponding to the
265      * source modifier {@link Modifier#ABSTRACT abstract}, with a mask
266      * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
267      */
268     ABSTRACT(Modifier.ABSTRACT, true,
269              Location.SET_CLASS_METHOD_INNER_CLASS,
270              List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
271 
272     /**
273      * The access flag {@code ACC_STRICT}, corresponding to the source
274      * modifier {@link Modifier#STRICT strictfp}, with a mask value of
275      * <code>{@value "0x%04x" Modifier#STRICT}</code>.
276      *
277      * @apiNote
278      * The {@code ACC_STRICT} access flag is defined for class file
279      * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
280      * corresponding to Java SE 1.2 through 16.
281      */
282     STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
283            List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
284                    Map.entry(RELEASE_1, Location.EMPTY_SET))),
285 
286     /**
287      * The access flag {@code ACC_STRICT_INIT}, with a mask value of
288      * <code>{@value "0x%04x" java.lang.classfile.ClassFile#ACC_STRICT_INIT}</code>.
289      *
290      * @jvms 4.5 Fields
291      * @since Valhalla
292      */
293     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
294     STRICT_INIT(ACC_STRICT_INIT, false,
295                 Location.SET_FIELD,
296                 List.of(Map.entry(latest(), Location.EMPTY_SET))),
297 
298     /**
299      * The access flag {@code ACC_SYNTHETIC} with a mask value of
300      * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
301      * @see Class#isSynthetic()
302      * @see Executable#isSynthetic()
303      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
304      */
305     SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
306               List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
307                       Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
308                       Map.entry(RELEASE_4, Location.EMPTY_SET))),
309 
310     /**
311      * The access flag {@code ACC_ANNOTATION} with a mask value of
312      * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
313      * @see Class#isAnnotation()
314      */
315     ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
316                List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
317 
318     /**
319      * The access flag {@code ACC_ENUM} with a mask value of
320      * <code>{@value "0x%04x" Modifier#ENUM}</code>.
321      * @see Class#isEnum()
322      */
323     ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS,
324          List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
325 
326     /**
327      * The access flag {@code ACC_MANDATED} with a mask value of
328      * <code>{@value "0x%04x" Modifier#MANDATED}</code>.
329      */
330     MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9,
331              List.of(Map.entry(RELEASE_8, Location.SET_METHOD_PARAM),
332                      Map.entry(RELEASE_7, Location.EMPTY_SET))),
333 
334     /**
335      * The access flag {@code ACC_MODULE} with a mask value of {@code
336      * 0x8000}.
337      */
338     MODULE(0x0000_8000, false, Location.SET_CLASS,
339            List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
340     ;
341 
342     // May want to override toString for a different enum constant ->
343     // name mapping.
344 
345     private final int mask;
346     private final boolean sourceModifier;
347 
348     // immutable
349     private final Set<Location> locations;
350     // historical locations up to a given version; immutable
351     private final List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations;
352 
353     private AccessFlag(int mask,
354                        boolean sourceModifier,
355                        Set<Location> locations,
356                        List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations) {
357         this.mask = mask;
358         this.sourceModifier = sourceModifier;
359         this.locations = locations;
360         this.historicalLocations = Location.ensureHistoryOrdered(historicalLocations);
361     }
362 
363     /**
364      * {@return the corresponding mask for the access flag}  The mask has
365      * exactly one bit set and is in the range of {@code char}.
366      */
367     public int mask() {
368         return mask;
369     }
370 
371     /**
372      * {@return whether or not this flag has a directly corresponding
373      * modifier in the Java programming language}
374      */
375     public boolean sourceModifier() {
376         return sourceModifier;
377     }
378 
379     /**
380      * {@return locations this flag can be applied to in the current class file
381      * format version}
382      * <p>
383      * This method returns an empty set if this flag is not defined in
384      * the current class file format version.
385      */
386     public Set<Location> locations() {
387         return locations(latest());
388     }
389 
390     /**
391      * {@return locations this flag can be applied to in the given class file
392      * format version}
393      * <p>
394      * This method returns an empty set if this flag is not defined in
395      * the given {@code cffv}.
396      *
397      * @param cffv the class file format version to use
398      * @throws NullPointerException if the parameter is {@code null}
399      */
400     public Set<Location> locations(ClassFileFormatVersion cffv) {
401         return Location.findInHistory(locations, historicalLocations, cffv);
402     }
403 
404     /**
405      * {@return an unmodifiable set of access flags for the given mask value
406      * appropriate for the location in the current class file format version}
407      *
408      * @param mask bit mask of access flags
409      * @param location context to interpret mask value
410      * @throws IllegalArgumentException if the mask contains bit
411      * positions not defined for the location in the current class file format
412      * @throws NullPointerException if {@code location} is {@code null}
413      */
414     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
415         return maskToAccessFlags(mask, location, latest());
416     }
417 
418     /**
419      * {@return an unmodifiable set of access flags for the given mask value
420      * appropriate for the location in the given class file format version}
421      *
422      * @param mask bit mask of access flags
423      * @param location context to interpret mask value
424      * @param cffv the class file format to interpret mask value
425      * @throws IllegalArgumentException if the mask contains bit
426      * positions not defined for the location in the given class file format
427      * @throws NullPointerException if {@code location} or {@code cffv} is {@code null}
428      * @since 25
429      */
430     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location, ClassFileFormatVersion cffv) {
431         var definition = findDefinition(location, cffv);  // null checks location
432         int unmatchedMask = mask & (~location.flagsMask(cffv));  // null checks cffv
433         if (unmatchedMask != 0) {
434             throw new IllegalArgumentException("Unmatched bit position 0x" +
435                     Integer.toHexString(unmatchedMask) +
436                     " for location " + location +
437                     " for class file format " + cffv);
438         }
439         return new AccessFlagSet(definition, mask);
440     }
441 
442     /**
443      * A location within a {@code class} file where flags can be applied.
444      * <p>
445      * Note that since these locations represent {@code class} file structures
446      * rather than language structures, many language structures, such
447      * as constructors and interfaces, are <em>not</em> present.
448      * @since 20
449      */
450     public enum Location {
451         /**
452          * Class location.
453          *
454          * @see Class#accessFlags()
455          * @see ClassModel#flags()
456          * @see Modifier#classModifiers()
457          * @see Modifier#interfaceModifiers()
458          * @jvms 4.1 The {@code ClassFile} Structure
459          */
460         CLASS(ACC_PUBLIC | ACC_FINAL | ACC_IDENTITY |
461               ACC_INTERFACE | ACC_ABSTRACT |
462               ACC_SYNTHETIC | ACC_ANNOTATION |
463               ACC_ENUM | ACC_MODULE,
464               List.of(Map.entry(RELEASE_8, // no module
465                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
466                                 ACC_INTERFACE | ACC_ABSTRACT |
467                                 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
468                       Map.entry(RELEASE_4, // no synthetic, annotation, enum
469                                 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
470                                 ACC_INTERFACE | ACC_ABSTRACT))),
471 
472         /**
473          * Field location.
474          *
475          * @see Field#accessFlags()
476          * @see FieldModel#flags()
477          * @see Modifier#fieldModifiers()
478          * @jvms 4.5 Fields
479          */
480         FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
481               ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
482               ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | ACC_STRICT_INIT,
483               List.of(Map.entry(latest(), // no strict_init
484                                 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
485                                 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
486                                 ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM),
487                       Map.entry(RELEASE_4, // no synthetic, enum
488                                 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
489                                 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
490                                 ACC_TRANSIENT))),
491 
492         /**
493          * Method location.
494          *
495          * @see Executable#accessFlags()
496          * @see MethodModel#flags()
497          * @see Modifier#methodModifiers()
498          * @see Modifier#constructorModifiers()
499          * @jvms 4.6 Methods
500          */
501         METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
502                ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
503                ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
504                ACC_ABSTRACT | ACC_SYNTHETIC,
505                List.of(Map.entry(RELEASE_16, // had strict
506                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
507                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
508                                  ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
509                                  ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
510                        Map.entry(RELEASE_4, // no bridge, varargs, synthetic
511                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
512                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
513                                  ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
514                        Map.entry(RELEASE_1, // no strict
515                                  ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
516                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
517                                  ACC_NATIVE | ACC_ABSTRACT))),
518 
519         /**
520          * Inner class location.
521          *
522          * @see Class#accessFlags()
523          * @see InnerClassInfo#flags()
524          * @see Modifier#classModifiers()
525          * @see Modifier#interfaceModifiers()
526          * @jvms 4.7.6 The {@code InnerClasses} Attribute
527          */
528         INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_IDENTITY |
529                     ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
530                     ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
531                     List.of(Map.entry(latest(), // no identity
532                                       ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
533                                       ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
534                                       ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
535                             Map.entry(RELEASE_4, // no synthetic, annotation, enum
536                                       ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
537                                       ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
538                                       ACC_ABSTRACT),
539                             Map.entry(RELEASE_0, 0))), // did not exist
540 
541         /**
542          * Method parameter location.
543          *
544          * @see Parameter#accessFlags()
545          * @see MethodParameterInfo#flags()
546          * @see Modifier#parameterModifiers()
547          * @jvms 4.7.24 The {@code MethodParameters} Attribute
548          */
549         METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
550                          List.of(Map.entry(RELEASE_7, 0))),  // did not exist
551 
552         /**
553          * Module location.
554          *
555          * @see ModuleDescriptor#accessFlags()
556          * @see ModuleAttribute#moduleFlags()
557          * @jvms 4.7.25 The {@code Module} Attribute
558          */
559         MODULE(ACC_OPEN | ACC_SYNTHETIC | ACC_MANDATED,
560                List.of(Map.entry(RELEASE_8, 0))),  // did not exist
561 
562         /**
563          * Module requires location.
564          *
565          * @see ModuleDescriptor.Requires#accessFlags()
566          * @see ModuleRequireInfo#requiresFlags()
567          * @jvms 4.7.25 The {@code Module} Attribute
568          */
569         MODULE_REQUIRES(ACC_TRANSITIVE | ACC_STATIC_PHASE | ACC_SYNTHETIC | ACC_MANDATED,
570                         List.of(Map.entry(RELEASE_8, 0))),  // did not exist
571 
572         /**
573          * Module exports location.
574          *
575          * @see ModuleDescriptor.Exports#accessFlags()
576          * @see ModuleExportInfo#exportsFlags()
577          * @jvms 4.7.25 The {@code Module} Attribute
578          */
579         MODULE_EXPORTS(ACC_SYNTHETIC | ACC_MANDATED,
580                        List.of(Map.entry(RELEASE_8, 0))),  // did not exist
581 
582         /**
583          * Module opens location.
584          *
585          * @see ModuleDescriptor.Opens#accessFlags()
586          * @see ModuleOpenInfo#opensFlags()
587          * @jvms 4.7.25 The {@code Module} Attribute
588          */
589         MODULE_OPENS(ACC_SYNTHETIC | ACC_MANDATED,
590                      List.of(Map.entry(RELEASE_8, 0))),  // did not exist
591         ;
592 
593         // Repeated sets of locations used by AccessFlag constants
594         private static final Set<Location> EMPTY_SET = Set.of();
595         private static final Set<Location> SET_MODULE = Set.of(MODULE);
596         private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS =
597             Set.of(CLASS, METHOD, INNER_CLASS);
598         private static final Set<Location> SET_CLASS_FIELD_METHOD =
599             Set.of(CLASS, FIELD, METHOD);
600         private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS =
601             Set.of(CLASS, FIELD, INNER_CLASS);
602         private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS =
603             Set.of(CLASS, FIELD, METHOD, INNER_CLASS);
604         private static final Set<Location> SET_CLASS_METHOD =
605             Set.of(CLASS, METHOD);
606         private static final Set<Location> SET_FIELD_METHOD =
607             Set.of(FIELD, METHOD);
608         private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
609             Set.of(FIELD, METHOD, INNER_CLASS);
610         private static final Set<Location> SET_METHOD = Set.of(METHOD);
611         private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER);
612         private static final Set<Location> SET_FIELD = Set.of(FIELD);
613         private static final Set<Location> SET_CLASS = Set.of(CLASS);
614         private static final Set<Location> SET_CLASS_INNER_CLASS =
615             Set.of(CLASS, INNER_CLASS);
616         private static final Set<Location> SET_MODULE_REQUIRES =
617             Set.of(MODULE_REQUIRES);
618         private static final Set<Location> SET_FINAL_8 =
619             Set.of(CLASS, FIELD, METHOD,
620                    INNER_CLASS,     /* added in 1.1 */
621                    METHOD_PARAMETER); /* added in 8 */
622         private static final Set<Location> SET_SYNTHETIC_5 =
623               Set.of(CLASS, FIELD, METHOD,
624                      INNER_CLASS);
625         private static final Set<Location> SET_SYNTHETIC_8 =
626               Set.of(CLASS, FIELD, METHOD,
627                      INNER_CLASS, METHOD_PARAMETER);
628         private static final Set<Location> SET_SYNTHETIC_9 =
629               // Added as an access flag in 5.0
630               Set.of(CLASS, FIELD, METHOD,
631                      INNER_CLASS,
632                      METHOD_PARAMETER, // Added in 8
633                      // Module-related items added in 9
634                      MODULE, MODULE_REQUIRES,
635                      MODULE_EXPORTS, MODULE_OPENS);
636         private static final Set<Location> SET_MANDATED_9 =
637             Set.of(METHOD_PARAMETER, // From 8
638                    // Starting in 9
639                    MODULE, MODULE_REQUIRES,
640                    MODULE_EXPORTS, MODULE_OPENS);
641 
642         private final int flagsMask;
643         private final List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks;
644 
645         Location(int flagsMask,
646                  List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks) {
647             this.flagsMask = flagsMask;
648             this.historicalFlagsMasks = ensureHistoryOrdered(historicalFlagsMasks);
649         }
650 
651         // Ensures the historical versions are from newest to oldest and do not include the latest
652         // These 2 utilities reside in Location because Location must be initialized before AccessFlag
653         private static <T> List<Map.Entry<ClassFileFormatVersion, T>> ensureHistoryOrdered(
654                 List<Map.Entry<ClassFileFormatVersion, T>> history) {
655             ClassFileFormatVersion lastVersion = CURRENT_PREVIEW_FEATURES;
656             for (var e : history) {
657                 var historyVersion = e.getKey();
658                 if (lastVersion.compareTo(historyVersion) <= 0) {
659                     throw new IllegalArgumentException("Versions out of order");
660                 }
661                 lastVersion = historyVersion;
662             }
663             return history;
664         }
665 
666         private static <T> T findInHistory(T candidate, List<Map.Entry<ClassFileFormatVersion, T>> history,
667                                            ClassFileFormatVersion cffv) {
668             Objects.requireNonNull(cffv);
669             for (var e : history) {
670                 if (e.getKey().compareTo(cffv) < 0) {
671                     // last version found was valid
672                     return candidate;
673                 }
674                 candidate = e.getValue();
675             }
676             return candidate;
677         }
678 
679         /**
680          * {@return the union of masks of all access flags defined for
681          * this location in the current class file format version}
682          * <p>
683          * This method returns {@code 0} if this location does not exist in
684          * the current class file format version.
685          *
686          * @since 25
687          */
688         public int flagsMask() {
689             return flagsMask(latest());
690         }
691 
692         /**
693          * {@return the union of masks of all access flags defined for
694          * this location in the given class file format version}
695          * <p>
696          * This method returns {@code 0} if this location does not exist in
697          * the given {@code cffv}.
698          *
699          * @param cffv the class file format version
700          * @throws NullPointerException if {@code cffv} is {@code null}
701          * @since 25
702          */
703         public int flagsMask(ClassFileFormatVersion cffv) {
704             return findInHistory(flagsMask, historicalFlagsMasks, cffv);
705         }
706 
707         /**
708          * {@return the set of access flags defined for this location in the
709          * current class file format version}  The set is immutable.
710          * <p>
711          * This method returns an empty set if this location does not exist
712          * in the current class file format version.
713          *
714          * @since 25
715          */
716         public Set<AccessFlag> flags() {
717             return flags(latest());
718         }
719 
720         /**
721          * {@return the set of access flags defined for this location in the
722          * given class file format version}  The set is immutable.
723          * <p>
724          * This method returns an empty set if this location does not exist
725          * in the given {@code cffv}.
726          *
727          * @param cffv the class file format version
728          * @throws NullPointerException if {@code cffv} is {@code null}
729          * @since 25
730          */
731         public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
732             // implicit null check cffv
733             return new AccessFlagSet(findDefinition(this, cffv), flagsMask(cffv));
734         }
735     }
736 
737     private static AccessFlag[] createDefinition(AccessFlag... known) {
738         var ret = new AccessFlag[Character.SIZE];
739         for (var flag : known) {
740             var mask = flag.mask;
741             int pos = Integer.numberOfTrailingZeros(mask);
742             assert ret[pos] == null : ret[pos] + " " + flag;
743             ret[pos] = flag;
744         }
745         return ret;
746     }
747 
748     private static AccessFlag[] findDefinition(Location location, ClassFileFormatVersion cffv) {
749         return switch (location) {
750             case CLASS -> cffv == CURRENT_PREVIEW_FEATURES ? CLASS_PREVIEW_FLAGS : CLASS_FLAGS;
751             case FIELD -> cffv == CURRENT_PREVIEW_FEATURES ? FIELD_PREVIEW_FLAGS : FIELD_FLAGS;
752             case METHOD -> METHOD_FLAGS;
753             case INNER_CLASS -> cffv == CURRENT_PREVIEW_FEATURES ? INNER_CLASS_PREVIEW_FLAGS : INNER_CLASS_FLAGS;
754             case METHOD_PARAMETER -> METHOD_PARAMETER_FLAGS;
755             case MODULE -> MODULE_FLAGS;
756             case MODULE_REQUIRES -> MODULE_REQUIRES_FLAGS;
757             case MODULE_EXPORTS -> MODULE_EXPORTS_FLAGS;
758             case MODULE_OPENS -> MODULE_OPENS_FLAGS;
759         };
760     }
761 
762     private static final @Stable AccessFlag[] // Can use stable array and lazy init in the future
763             CLASS_FLAGS         = createDefinition(PUBLIC, FINAL, SUPER, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
764             CLASS_PREVIEW_FLAGS = createDefinition(PUBLIC, FINAL, IDENTITY, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE), // identity
765             FIELD_FLAGS         = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM),
766             FIELD_PREVIEW_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT), // strict
767             METHOD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, BRIDGE, VARARGS, NATIVE, ABSTRACT, STRICT, SYNTHETIC),
768             INNER_CLASS_FLAGS         = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),
769             INNER_CLASS_PREVIEW_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, IDENTITY, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),  // identity
770             METHOD_PARAMETER_FLAGS = createDefinition(FINAL, SYNTHETIC, MANDATED),
771             MODULE_FLAGS = createDefinition(OPEN, SYNTHETIC, MANDATED),
772             MODULE_REQUIRES_FLAGS = createDefinition(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED),
773             MODULE_EXPORTS_FLAGS = createDefinition(SYNTHETIC, MANDATED),
774             MODULE_OPENS_FLAGS = createDefinition(SYNTHETIC, MANDATED);
775 
776     private static int undefinedMask(AccessFlag[] definition, int mask) {
777         assert definition.length == Character.SIZE;
778         int definedMask = 0;
779         for (int i = 0; i < Character.SIZE; i++) {
780             if (definition[i] != null) {
781                 definedMask |= 1 << i;
782             }
783         }
784         return mask & ~definedMask;
785     }
786 
787     private static final class AccessFlagSet extends AbstractSet<AccessFlag> {
788         private final @Stable AccessFlag[] definition;
789         private final int mask;
790 
791         // all mutating methods throw UnsupportedOperationException
792         @Override public boolean add(AccessFlag e) { throw uoe(); }
793         @Override public boolean addAll(Collection<? extends AccessFlag> c) { throw uoe(); }
794         @Override public void    clear() { throw uoe(); }
795         @Override public boolean remove(Object o) { throw uoe(); }
796         @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
797         @Override public boolean removeIf(Predicate<? super AccessFlag> filter) { throw uoe(); }
798         @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
799         private static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
800 
801         private AccessFlagSet(AccessFlag[] definition, int mask) {
802             assert undefinedMask(definition, mask) == 0 : mask;
803             this.definition = definition;
804             this.mask = mask;
805         }
806 
807         @Override
808         public Iterator<AccessFlag> iterator() {
809             return new AccessFlagIterator(definition, mask);
810         }
811 
812         @Override
813         public void forEach(Consumer<? super AccessFlag> action) {
814             Objects.requireNonNull(action); // in case of empty
815             for (int i = 0; i < Character.SIZE; i++) {
816                 if ((mask & (1 << i)) != 0) {
817                     action.accept(definition[i]);
818                 }
819             }
820         }
821 
822         private static final class AccessFlagIterator implements Iterator<AccessFlag> {
823             private final @Stable AccessFlag[] definition;
824             private int remainingMask;
825 
826             private AccessFlagIterator(AccessFlag[] definition, int remainingMask) {
827                 this.definition = definition;
828                 this.remainingMask = remainingMask;
829             }
830 
831             @Override
832             public boolean hasNext() {
833                 return remainingMask != 0;
834             }
835 
836             @Override
837             public AccessFlag next() {
838                 int flagBit = Integer.lowestOneBit(remainingMask);
839                 if (flagBit == 0) {
840                     throw new NoSuchElementException();
841                 }
842                 remainingMask &= ~flagBit;
843                 return definition[Integer.numberOfTrailingZeros(flagBit)];
844             }
845         }
846 
847         @Override
848         public int size() {
849             return Integer.bitCount(mask);
850         }
851 
852         @Override
853         public boolean contains(Object o) {
854             if (Objects.requireNonNull(o) instanceof AccessFlag flag) {
855                 int bit = flag.mask;
856                 return (bit & mask) != 0 && definition[Integer.numberOfTrailingZeros(bit)] == flag;
857             }
858             return false;
859         }
860 
861         @Override
862         public boolean isEmpty() {
863             return mask == 0;
864         }
865     }
866 }