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