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 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;
 51 
 52 import jdk.internal.vm.annotation.Stable;
 53 
 54 import static java.lang.classfile.ClassFile.*;
 55 import static java.lang.reflect.ClassFileFormatVersion.*;
 56 
 57 /**
 58  * Represents a JVM access or module-related flag on a runtime member,
 59  * such as a {@linkplain Class class}, {@linkplain Field field}, or
 60  * {@linkplain Executable method}.
 61  *
 62  * <P>JVM access and module-related flags are related to, but distinct
 63  * from Java language {@linkplain Modifier modifiers}. Some modifiers
 64  * and access flags have a one-to-one correspondence, such as {@code
 65  * public}. In other cases, some language-level modifiers do
 66  * <em>not</em> have an access flag, such as {@code sealed} (JVMS
 67  * {@jvms 4.7.31}) and some access flags have no corresponding
 68  * modifier, such as {@linkplain #SYNTHETIC synthetic}.
 69  *
 70  * <p>The values for the constants representing the access and module
 71  * flags are taken from sections of <cite>The Java Virtual Machine
 72  * Specification</cite> including {@jvms 4.1} (class access and
 73  * property modifiers), {@jvms 4.5} (field access and property flags),
 74  * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
 75  * (nested class access and property flags), {@jvms 4.7.24} (method
 76  * parameters), and {@jvms 4.7.25} (module flags and requires,
 77  * exports, and opens flags).
 78  *
 79  * <p>The {@linkplain #mask() mask} values for the different access
 80  * flags are <em>not</em> distinct. Flags are defined for different
 81  * kinds of JVM structures and the same bit position has different
 82  * meanings in different contexts. For example, {@code 0x0000_0040}
 83  * indicates a {@link #VOLATILE volatile} field but a {@linkplain
 84  * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
 85  * #TRANSIENT transient} field but a {@linkplain #VARARGS variable
 86  * arity (varargs)} method.
 87  *
 88  * @implSpec
 89  * The access flag constants are ordered by non-decreasing mask
 90  * value; that is the mask value of a constant is greater than or
 91  * equal to the mask value of an immediate neighbor to its (syntactic)
 92  * left. If new constants are added, this property will be
 93  * maintained. That implies new constants will not necessarily be
 94  * added at the end of the existing list.
 95  *
 96  * @apiNote
 97  * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new
 98  * {@linkplain Runtime.Version#feature() feature release}. A new class
 99  * file version may define new access flags or retire old ones. {@code
100  * AccessFlag} is intended to model the set of access flags across
101  * class file format versions. The range of versions an access flag is
102  * recognized is not explicitly indicated in this API. See the current
103  * <cite>The Java Virtual Machine Specification</cite> for
104  * details. Unless otherwise indicated, access flags can be assumed to
105  * be recognized in the {@linkplain Runtime#version() current
106  * version}.
107  *
108  * @see java.lang.reflect.Modifier
109  * @see java.lang.module.ModuleDescriptor.Modifier
110  * @see java.lang.module.ModuleDescriptor.Requires.Modifier
111  * @see java.lang.module.ModuleDescriptor.Exports.Modifier
112  * @see java.lang.module.ModuleDescriptor.Opens.Modifier
113  * @see java.compiler/javax.lang.model.element.Modifier
114  * @since 20
115  */
116 @SuppressWarnings("doclint:reference") // cross-module link
117 public enum AccessFlag {
118     /**
119      * The access flag {@code ACC_PUBLIC}, corresponding to the source
120      * modifier {@link Modifier#PUBLIC public}, with a mask value of
121      * <code>{@value "0x%04x" Modifier#PUBLIC}</code>.
122      */
123     PUBLIC(Modifier.PUBLIC, true,
124            Location.SET_CLASS_FIELD_METHOD_INNER_CLASS,
125            List.of(Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
126 
127     /**
128      * The access flag {@code ACC_PRIVATE}, corresponding to the
129      * source modifier {@link Modifier#PRIVATE private}, with a mask
130      * value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>.
131      */
132     PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS,
133             List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
134 
135     /**
136      * The access flag {@code ACC_PROTECTED}, corresponding to the
137      * source modifier {@link Modifier#PROTECTED protected}, with a mask
138      * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>.
139      */
140     PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS,
141               List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
142 
143     /**
144      * The access flag {@code ACC_STATIC}, corresponding to the source
145      * modifier {@link Modifier#STATIC static}, with a mask value of
146      * <code>{@value "0x%04x" Modifier#STATIC}</code>.
147      */
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
207      * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
208      */
209     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, List.of()),
210 
211     /**
212      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
213      * value of {@code 0x0040}.
214      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
215      */
216     STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
217                  List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
218 
219     /**
220      * The access flag {@code ACC_VOLATILE}, corresponding to the
221      * source modifier {@link Modifier#VOLATILE volatile}, with a mask
222      * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
223      */
224     VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, List.of()),
225 
226     /**
227      * The access flag {@code ACC_BRIDGE} with a mask value of
228      * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
229      * @see Method#isBridge()
230      */
231     BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
232            List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
233 
234     /**
235      * The access flag {@code ACC_TRANSIENT}, corresponding to the
236      * source modifier {@link Modifier#TRANSIENT transient}, with a
237      * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>.
238      */
239     TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, List.of()),
240 
241     /**
242      * The access flag {@code ACC_VARARGS} with a mask value of
243      * <code>{@value "0x%04x" Modifier#VARARGS}</code>.
244      * @see Executable#isVarArgs()
245      */
246     VARARGS(Modifier.VARARGS, false, Location.SET_METHOD,
247             List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
248 
249     /**
250      * The access flag {@code ACC_NATIVE}, corresponding to the source
251      * modifier {@link Modifier#NATIVE native}, with a mask value of
252      * <code>{@value "0x%04x" Modifier#NATIVE}</code>.
253      */
254     NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, List.of()),
255 
256     /**
257      * The access flag {@code ACC_INTERFACE} with a mask value of
258      * {@code 0x0200}.
259      * @see Class#isInterface()
260      */
261     INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS,
262               List.of(Map.entry(RELEASE_0, Location.SET_CLASS))),
263 
264     /**
265      * The access flag {@code ACC_ABSTRACT}, corresponding to the
266      * source modifier {@link Modifier#ABSTRACT abstract}, with a mask
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 
319     /**
320      * The access flag {@code ACC_ENUM} with a mask value of
321      * <code>{@value "0x%04x" Modifier#ENUM}</code>.
322      * @see Class#isEnum()
323      */
324     ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS,
325          List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
326 
327     /**
328      * The access flag {@code ACC_MANDATED} with a mask value of
329      * <code>{@value "0x%04x" Modifier#MANDATED}</code>.
330      */
331     MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9,
332              List.of(Map.entry(RELEASE_8, Location.SET_METHOD_PARAM),
333                      Map.entry(RELEASE_7, Location.EMPTY_SET))),
334 
335     /**
336      * The access flag {@code ACC_MODULE} with a mask value of {@code
337      * 0x8000}.
338      */
339     MODULE(0x0000_8000, false, Location.SET_CLASS,
340            List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
341     ;
342 
343     // May want to override toString for a different enum constant ->
344     // name mapping.
345 
346     private final int mask;
347     private final boolean sourceModifier;
348 
349     // immutable
350     private final Set<Location> locations;
351     // historical locations up to a given version; immutable
352     private final List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations;
353 
354     private AccessFlag(int mask,
355                        boolean sourceModifier,
356                        Set<Location> locations,
357                        List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations) {
358         this.mask = mask;
359         this.sourceModifier = sourceModifier;
360         this.locations = locations;
361         this.historicalLocations = Location.ensureHistoryOrdered(historicalLocations);
362     }
363 
364     /**
365      * {@return the corresponding mask for the access flag}  The mask has
366      * exactly one bit set and is in the range of {@code char}.
367      */
368     public int mask() {
369         return mask;
370     }
371 
372     /**
373      * {@return whether or not this flag has a directly corresponding
374      * modifier in the Java programming language}
375      */
376     public boolean sourceModifier() {
377         return sourceModifier;
378     }
379 
380     /**
381      * {@return locations this flag can be applied to in the current class file
382      * format version}
383      * <p>
384      * This method returns an empty set if this flag is not defined in
385      * the current class file format version.
386      */
387     public Set<Location> locations() {
388         return locations;
389     }
390 
391     /**
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 |
514                                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
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         /**
556          * Module location.
557          *
558          * @see ModuleDescriptor#accessFlags()
559          * @see ModuleAttribute#moduleFlags()
560          * @jvms 4.7.25 The {@code Module} Attribute
561          */
562         MODULE(ACC_OPEN | ACC_SYNTHETIC | ACC_MANDATED,
563                List.of(Map.entry(RELEASE_8, 0))),  // did not exist
564 
565         /**
566          * Module requires location.
567          *
568          * @see ModuleDescriptor.Requires#accessFlags()
569          * @see ModuleRequireInfo#requiresFlags()
570          * @jvms 4.7.25 The {@code Module} Attribute
571          */
572         MODULE_REQUIRES(ACC_TRANSITIVE | ACC_STATIC_PHASE | ACC_SYNTHETIC | ACC_MANDATED,
573                         List.of(Map.entry(RELEASE_8, 0))),  // did not exist
574 
575         /**
576          * Module exports location.
577          *
578          * @see ModuleDescriptor.Exports#accessFlags()
579          * @see ModuleExportInfo#exportsFlags()
580          * @jvms 4.7.25 The {@code Module} Attribute
581          */
582         MODULE_EXPORTS(ACC_SYNTHETIC | ACC_MANDATED,
583                        List.of(Map.entry(RELEASE_8, 0))),  // did not exist
584 
585         /**
586          * Module opens location.
587          *
588          * @see ModuleDescriptor.Opens#accessFlags()
589          * @see ModuleOpenInfo#opensFlags()
590          * @jvms 4.7.25 The {@code Module} Attribute
591          */
592         MODULE_OPENS(ACC_SYNTHETIC | ACC_MANDATED,
593                      List.of(Map.entry(RELEASE_8, 0))),  // did not exist
594         ;
595 
596         // Repeated sets of locations used by AccessFlag constants
597         private static final Set<Location> EMPTY_SET = Set.of();
598         private static final Set<Location> SET_MODULE = Set.of(MODULE);
599         private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS =
600             Set.of(CLASS, METHOD, INNER_CLASS);
601         private static final Set<Location> SET_CLASS_FIELD_METHOD =
602             Set.of(CLASS, FIELD, METHOD);
603         private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS =
604             Set.of(CLASS, FIELD, INNER_CLASS);
605         private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS =
606             Set.of(CLASS, FIELD, METHOD, INNER_CLASS);
607         private static final Set<Location> SET_CLASS_METHOD =
608             Set.of(CLASS, METHOD);
609         private static final Set<Location> SET_FIELD_METHOD =
610             Set.of(FIELD, METHOD);
611         private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
612             Set.of(FIELD, METHOD, INNER_CLASS);
613         private static final Set<Location> SET_METHOD = Set.of(METHOD);
614         private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER);
615         private static final Set<Location> SET_FIELD = Set.of(FIELD);
616         private static final Set<Location> SET_CLASS = Set.of(CLASS);
617         private static final Set<Location> SET_CLASS_INNER_CLASS =
618             Set.of(CLASS, INNER_CLASS);
619         private static final Set<Location> SET_MODULE_REQUIRES =
620             Set.of(MODULE_REQUIRES);
621         private static final Set<Location> SET_FINAL_8 =
622             Set.of(CLASS, FIELD, METHOD,
623                    INNER_CLASS,     /* added in 1.1 */
624                    METHOD_PARAMETER); /* added in 8 */
625         private static final Set<Location> SET_SYNTHETIC_5 =
626               Set.of(CLASS, FIELD, METHOD,
627                      INNER_CLASS);
628         private static final Set<Location> SET_SYNTHETIC_8 =
629               Set.of(CLASS, FIELD, METHOD,
630                      INNER_CLASS, METHOD_PARAMETER);
631         private static final Set<Location> SET_SYNTHETIC_9 =
632               // Added as an access flag in 5.0
633               Set.of(CLASS, FIELD, METHOD,
634                      INNER_CLASS,
635                      METHOD_PARAMETER, // Added in 8
636                      // Module-related items added in 9
637                      MODULE, MODULE_REQUIRES,
638                      MODULE_EXPORTS, MODULE_OPENS);
639         private static final Set<Location> SET_MANDATED_9 =
640             Set.of(METHOD_PARAMETER, // From 8
641                    // Starting in 9
642                    MODULE, MODULE_REQUIRES,
643                    MODULE_EXPORTS, MODULE_OPENS);
644 
645         private final int flagsMask;
646         private final List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks;
647 
648         Location(int flagsMask,
649                  List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks) {
650             this.flagsMask = flagsMask;
651             this.historicalFlagsMasks = ensureHistoryOrdered(historicalFlagsMasks);
652         }
653 
654         // Ensures the historical versions are from newest to oldest and do not include the latest
655         // These 2 utilities reside in Location because Location must be initialized before AccessFlag
656         private static <T> List<Map.Entry<ClassFileFormatVersion, T>> ensureHistoryOrdered(
657                 List<Map.Entry<ClassFileFormatVersion, T>> history) {
658             ClassFileFormatVersion lastVersion = ClassFileFormatVersion.latest();
659             for (var e : history) {
660                 var historyVersion = e.getKey();
661                 if (lastVersion.compareTo(historyVersion) <= 0) {
662                     throw new IllegalArgumentException("Versions out of order");
663                 }
664                 lastVersion = historyVersion;
665             }
666             return history;
667         }
668 
669         private static <T> T findInHistory(T candidate, List<Map.Entry<ClassFileFormatVersion, T>> history,
670                                            ClassFileFormatVersion cffv) {
671             Objects.requireNonNull(cffv);
672             for (var e : history) {
673                 if (e.getKey().compareTo(cffv) < 0) {
674                     // last version found was valid
675                     return candidate;
676                 }
677                 candidate = e.getValue();
678             }
679             return candidate;
680         }
681 
682         /**
683          * {@return the union of masks of all access flags defined for
684          * this location in the current class file format version}
685          * <p>
686          * This method returns {@code 0} if this location does not exist in
687          * the current class file format version.
688          *
689          * @since 25
690          */
691         public int flagsMask() {
692             return flagsMask;
693         }
694 
695         /**
696          * {@return the union of masks of all access flags defined for
697          * this location in the given class file format version}
698          * <p>
699          * This method returns {@code 0} if this location does not exist in
700          * the given {@code cffv}.
701          *
702          * @param cffv the class file format version
703          * @throws NullPointerException if {@code cffv} is {@code null}
704          * @since 25
705          */
706         public int flagsMask(ClassFileFormatVersion cffv) {
707             return findInHistory(flagsMask, historicalFlagsMasks, cffv);
708         }
709 
710         /**
711          * {@return the set of access flags defined for this location in the
712          * current class file format version}  The set is immutable.
713          * <p>
714          * This method returns an empty set if this location does not exist
715          * in the current class file format version.
716          *
717          * @since 25
718          */
719         public Set<AccessFlag> flags() {
720             return new AccessFlagSet(findDefinition(this), flagsMask());
721         }
722 
723         /**
724          * {@return the set of access flags defined for this location in the
725          * given class file format version}  The set is immutable.
726          * <p>
727          * This method returns an empty set if this location does not exist
728          * in the given {@code cffv}.
729          *
730          * @param cffv the class file format version
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;
792 
793         // all mutating methods throw UnsupportedOperationException
794         @Override public boolean add(AccessFlag e) { throw uoe(); }
795         @Override public boolean addAll(Collection<? extends AccessFlag> c) { throw uoe(); }
796         @Override public void    clear() { throw uoe(); }
797         @Override public boolean remove(Object o) { throw uoe(); }
798         @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
799         @Override public boolean removeIf(Predicate<? super AccessFlag> filter) { throw uoe(); }
800         @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
801         private static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
802 
803         private AccessFlagSet(AccessFlag[] definition, int mask) {
804             assert undefinedMask(definition, mask) == 0 : mask;
805             this.definition = definition;
806             this.mask = mask;
807         }
808 
809         @Override
810         public Iterator<AccessFlag> iterator() {
811             return new AccessFlagIterator(definition, mask);
812         }
813 
814         @Override
815         public void forEach(Consumer<? super AccessFlag> action) {
816             Objects.requireNonNull(action); // in case of empty
817             for (int i = 0; i < Character.SIZE; i++) {
818                 if ((mask & (1 << i)) != 0) {
819                     action.accept(definition[i]);
820                 }
821             }
822         }
823 
824         private static final class AccessFlagIterator implements Iterator<AccessFlag> {
825             private final @Stable AccessFlag[] definition;
826             private int remainingMask;
827 
828             private AccessFlagIterator(AccessFlag[] definition, int remainingMask) {
829                 this.definition = definition;
830                 this.remainingMask = remainingMask;
831             }
832 
833             @Override
834             public boolean hasNext() {
835                 return remainingMask != 0;
836             }
837 
838             @Override
839             public AccessFlag next() {
840                 int flagBit = Integer.lowestOneBit(remainingMask);
841                 if (flagBit == 0) {
842                     throw new NoSuchElementException();
843                 }
844                 remainingMask &= ~flagBit;
845                 return definition[Integer.numberOfTrailingZeros(flagBit)];
846             }
847         }
848 
849         @Override
850         public int size() {
851             return Integer.bitCount(mask);
852         }
853 
854         @Override
855         public boolean contains(Object o) {
856             if (Objects.requireNonNull(o) instanceof AccessFlag flag) {
857                 int bit = flag.mask;
858                 return (bit & mask) != 0 && definition[Integer.numberOfTrailingZeros(bit)] == flag;
859             }
860             return false;
861         }
862 
863         @Override
864         public boolean isEmpty() {
865             return mask == 0;
866         }
867     }
868 }