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