< prev index next >

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

Print this page

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



 28 import java.util.Collections;
 29 import java.util.Objects;
 30 import java.util.Map;
 31 import java.util.Set;
 32 import java.util.function.Function;
 33 import static java.util.Map.entry;
 34 
 35 /**
 36  * Represents a JVM access or module-related flag on a runtime member,
 37  * such as a {@linkplain Class class}, {@linkplain Field field}, or
 38  * {@linkplain Executable method}.
 39  *
 40  * <P>JVM access and module-related flags are related to, but distinct
 41  * from Java language {@linkplain Modifier modifiers}. Some modifiers
 42  * and access flags have a one-to-one correspondence, such as {@code
 43  * public}. In other cases, some language-level modifiers do
 44  * <em>not</em> have an access flag, such as {@code sealed} (JVMS
 45  * {@jvms 4.7.31}) and some access flags have no corresponding
 46  * modifier, such as {@linkplain #SYNTHETIC synthetic}.
 47  *

168            new Function<ClassFileFormatVersion, Set<Location>>() {
169               @Override
170               public Set<Location> apply(ClassFileFormatVersion cffv) {
171                   if (cffv.compareTo(ClassFileFormatVersion.RELEASE_8) >= 0) {
172                       return Location.SET_FINAL_8;
173                   } else {
174                       return (cffv == ClassFileFormatVersion.RELEASE_0) ?
175                           Location.SET_CLASS_FIELD_METHOD :
176                           Location.SET_CLASS_FIELD_METHOD_INNER_CLASS;
177                   }
178               }
179           }),
180 
181     /**
182      * The access flag {@code ACC_SUPER} with a mask value of {@code
183      * 0x0020}.
184      *
185      * @apiNote
186      * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
187      * flag as set in every class file (JVMS {@jvms 4.1}).




















188      */
189     SUPER(0x0000_0020, false, Location.SET_CLASS, null),










190 
191     /**
192      * The module flag {@code ACC_OPEN} with a mask value of {@code
193      * 0x0020}.
194      * @see java.lang.module.ModuleDescriptor#isOpen
195      */
196         OPEN(0x0000_0020, false, Location.SET_MODULE,
197              new Function<ClassFileFormatVersion, Set<Location>>() {
198                  @Override
199                  public Set<Location> apply(ClassFileFormatVersion cffv) {
200                      return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
201                          Location.SET_MODULE:
202                          Location.EMPTY_SET;}
203              }),
204 
205     /**
206      * The module requires flag {@code ACC_TRANSITIVE} with a mask
207      * value of {@code 0x0020}.
208      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
209      */
210     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
211                new Function<ClassFileFormatVersion, Set<Location>>() {
212                    @Override
213                    public Set<Location> apply(ClassFileFormatVersion cffv) {
214                        return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
215                            Location.SET_MODULE_REQUIRES:
216                            Location.EMPTY_SET;}
217                }),
218 
219     /**
220      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
221      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
222      * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
223      */
224     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, null),
225 
226     /**
227      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
228      * value of {@code 0x0040}.
229      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
230      */
231     STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
232                  new Function<ClassFileFormatVersion, Set<Location>>() {
233                      @Override
234                      public Set<Location> apply(ClassFileFormatVersion cffv) {
235                          return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
236                              Location.SET_MODULE_REQUIRES:
237                              Location.EMPTY_SET;}
238                  }),
239 
240    /**
241      * The access flag {@code ACC_VOLATILE}, corresponding to the
242      * source modifier {@link Modifier#VOLATILE volatile}, with a mask
243      * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
244      */
245     VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, null),
246 
247     /**
248      * The access flag {@code ACC_BRIDGE} with a mask value of
249      * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
250      * @see Method#isBridge()
251      */
252     BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
253            new Function<ClassFileFormatVersion, Set<Location>>() {
254                @Override
255                public Set<Location> apply(ClassFileFormatVersion cffv) {
256                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
257                        Location.SET_METHOD:
258                        Location.EMPTY_SET;}
259            }),
260 

318     /**
319      * The access flag {@code ACC_STRICT}, corresponding to the source
320      * modifier {@link Modifier#STRICT strictfp}, with a mask value of
321      * <code>{@value "0x%04x" Modifier#STRICT}</code>.
322      *
323      * @apiNote
324      * The {@code ACC_STRICT} access flag is defined for class file
325      * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
326      * corresponding to Java SE 1.2 through 16.
327      */
328     STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
329              new Function<ClassFileFormatVersion, Set<Location>>() {
330                @Override
331                public Set<Location> apply(ClassFileFormatVersion cffv) {
332                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_2)  >= 0 &&
333                            cffv.compareTo(ClassFileFormatVersion.RELEASE_16) <= 0) ?
334                        Location.SET_METHOD:
335                        Location.EMPTY_SET;}
336            }),
337 
























338     /**
339      * The access flag {@code ACC_SYNTHETIC} with a mask value of
340      * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
341      * @see Class#isSynthetic()
342      * @see Executable#isSynthetic()
343      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
344      */
345     SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
346               new Function<ClassFileFormatVersion, Set<Location>>() {
347                   @Override
348                   public Set<Location> apply(ClassFileFormatVersion cffv) {
349                       if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 )
350                           return Location.SET_SYNTHETIC_9;
351                       else {
352                           return
353                               switch(cffv) {
354                               case RELEASE_7 -> Location.SET_SYNTHETIC_7;
355                               case RELEASE_8 -> Location.SET_SYNTHETIC_8;
356                               default        -> Location.EMPTY_SET;
357                               };

469      * given class file format version}
470      * @param cffv the class file format version to use
471      * @throws NullPointerException if the parameter is {@code null}
472      */
473     public Set<Location> locations(ClassFileFormatVersion cffv) {
474         Objects.requireNonNull(cffv);
475         if (cffvToLocations == null) {
476             return locations;
477         } else {
478             return cffvToLocations.apply(cffv);
479         }
480     }
481 
482     /**
483      * {@return an unmodifiable set of access flags for the given mask value
484      * appropriate for the location in question}
485      *
486      * @param mask bit mask of access flags
487      * @param location context to interpret mask value
488      * @throws IllegalArgumentException if the mask contains bit
489      * positions not support for the location in question
490      */
491     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
492         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
493         for (var accessFlag : LocationToFlags.locationToFlags.get(location)) {
494             int accessMask = accessFlag.mask();
495             if ((mask &  accessMask) != 0) {
496                 result.add(accessFlag);
497                 mask = mask & ~accessMask;



498             }
499         }
500         if (mask != 0) {
501             throw new IllegalArgumentException("Unmatched bit position 0x" +
502                                                Integer.toHexString(mask) +
503                                                " for location " + location);
504         }
505         return Collections.unmodifiableSet(result);
506     }
507 






































508     /**
509      * A location within a class file where flags can be applied.
510      *
511      * Note that since these locations represent class file structures
512      * rather than language structures many language structures, such
513      * as constructors and interfaces, are <em>not</em> present.
514      * @since 20
515      */
516     public enum Location {
517         /**
518          * Class location.
519          * @jvms 4.1 The ClassFile Structure
520          */
521         CLASS,
522 
523         /**
524          * Field location.
525          * @jvms 4.5 Fields
526          */
527         FIELD,

606               Set.of(CLASS, FIELD, METHOD,
607                      INNER_CLASS, METHOD_PARAMETER);
608         private static final Set<Location> SET_SYNTHETIC_9 =
609               // Added as an access flag in 7
610               Set.of(CLASS, FIELD, METHOD,
611                      INNER_CLASS,
612                      METHOD_PARAMETER, // Added in 8
613                      // Module-related items added in 9
614                      MODULE, MODULE_REQUIRES,
615                      MODULE_EXPORTS, MODULE_OPENS);
616         private static final Set<Location> SET_MANDATED_9 =
617             Set.of(METHOD_PARAMETER, // From 8
618                    // Starting in 9
619                    MODULE, MODULE_REQUIRES,
620                    MODULE_EXPORTS, MODULE_OPENS);
621     }
622 
623     private static class LocationToFlags {
624         private static Map<Location, Set<AccessFlag>> locationToFlags =
625             Map.ofEntries(entry(Location.CLASS,
626                                 Set.of(PUBLIC, FINAL, SUPER,
627                                        INTERFACE, ABSTRACT,
628                                        SYNTHETIC, ANNOTATION,
629                                        ENUM, AccessFlag.MODULE)),
630                           entry(Location.FIELD,
631                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
632                                        STATIC, FINAL, VOLATILE,
633                                        TRANSIENT, SYNTHETIC, ENUM)),





634                           entry(Location.METHOD,
635                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
636                                        STATIC, FINAL, SYNCHRONIZED,
637                                        BRIDGE, VARARGS, NATIVE,
638                                        ABSTRACT, STRICT, SYNTHETIC)),
639                           entry(Location.INNER_CLASS,
640                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
641                                        STATIC, FINAL, INTERFACE, ABSTRACT,
642                                        SYNTHETIC, ANNOTATION, ENUM)),
643                           entry(Location.METHOD_PARAMETER,
644                                 Set.of(FINAL, SYNTHETIC, MANDATED)),
645                           entry(Location.MODULE,
646                                 Set.of(OPEN, SYNTHETIC, MANDATED)),
647                           entry(Location.MODULE_REQUIRES,
648                                 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
649                           entry(Location.MODULE_EXPORTS,
650                                 Set.of(SYNTHETIC, MANDATED)),
651                           entry(Location.MODULE_OPENS,
652                                 Set.of(SYNTHETIC, MANDATED)));
653     }
654 }

  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  *

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 

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                               };

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      * @since Valhalla
579      */
580     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
581                                                     ClassFileFormatVersion cffv) {
582         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
583         for (var accessFlag : AccessFlag.values()) {
584             int accessMask = accessFlag.mask();
585             if ((mask & accessMask) != 0) {
586                 var locations = accessFlag.locations(cffv);
587                 if (locations.contains(location)) {
588                     result.add(accessFlag);
589                     mask = mask & ~accessMask;
590                     if (mask == 0) {
591                         break;      // no more mask bits
592                     }
593                 }
594             }
595         }
596         if (mask != 0) {
597             throw new IllegalArgumentException("Unmatched bit position 0x" +
598                                                Integer.toHexString(mask) +
599                                                " for location " + location +
600                                                " for class file format version " + cffv);
601         }
602         return Collections.unmodifiableSet(result);
603     }
604 
605 
606     /**
607      * A location within a class file where flags can be applied.
608      *
609      * Note that since these locations represent class file structures
610      * rather than language structures many language structures, such
611      * as constructors and interfaces, are <em>not</em> present.
612      * @since 20
613      */
614     public enum Location {
615         /**
616          * Class location.
617          * @jvms 4.1 The ClassFile Structure
618          */
619         CLASS,
620 
621         /**
622          * Field location.
623          * @jvms 4.5 Fields
624          */
625         FIELD,

704               Set.of(CLASS, FIELD, METHOD,
705                      INNER_CLASS, METHOD_PARAMETER);
706         private static final Set<Location> SET_SYNTHETIC_9 =
707               // Added as an access flag in 7
708               Set.of(CLASS, FIELD, METHOD,
709                      INNER_CLASS,
710                      METHOD_PARAMETER, // Added in 8
711                      // Module-related items added in 9
712                      MODULE, MODULE_REQUIRES,
713                      MODULE_EXPORTS, MODULE_OPENS);
714         private static final Set<Location> SET_MANDATED_9 =
715             Set.of(METHOD_PARAMETER, // From 8
716                    // Starting in 9
717                    MODULE, MODULE_REQUIRES,
718                    MODULE_EXPORTS, MODULE_OPENS);
719     }
720 
721     private static class LocationToFlags {
722         private static Map<Location, Set<AccessFlag>> locationToFlags =
723             Map.ofEntries(entry(Location.CLASS,
724                                 Set.of(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER),
725                                        INTERFACE, ABSTRACT,
726                                        SYNTHETIC, ANNOTATION,
727                                        ENUM, AccessFlag.MODULE)),
728                           entry(Location.FIELD,
729                                 PreviewFeatures.isEnabled() ?
730                                         // STRICT_FIELD should be included only if preview is enabled
731                                         Set.of(PUBLIC, PRIVATE, PROTECTED,
732                                             STATIC, FINAL, VOLATILE,
733                                             TRANSIENT, SYNTHETIC, ENUM, STRICT_FIELD) :
734                                         Set.of(PUBLIC, PRIVATE, PROTECTED,
735                                                 STATIC, FINAL, VOLATILE,
736                                                 TRANSIENT, SYNTHETIC, ENUM)),
737                           entry(Location.METHOD,
738                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
739                                        STATIC, FINAL, SYNCHRONIZED,
740                                        BRIDGE, VARARGS, NATIVE,
741                                        ABSTRACT, STRICT, SYNTHETIC)),
742                           entry(Location.INNER_CLASS,
743                                           Set.of(PUBLIC, PRIVATE, PROTECTED, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER),
744                                                   STATIC, FINAL, INTERFACE, ABSTRACT,
745                                                   SYNTHETIC, ANNOTATION, ENUM)),
746                           entry(Location.METHOD_PARAMETER,
747                                 Set.of(FINAL, SYNTHETIC, MANDATED)),
748                           entry(Location.MODULE,
749                                 Set.of(OPEN, SYNTHETIC, MANDATED)),
750                           entry(Location.MODULE_REQUIRES,
751                                 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
752                           entry(Location.MODULE_EXPORTS,
753                                 Set.of(SYNTHETIC, MANDATED)),
754                           entry(Location.MODULE_OPENS,
755                                 Set.of(SYNTHETIC, MANDATED)));
756     }
757 }
< prev index next >