< 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 

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.RELEASE_22) >= 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      * source 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     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS)
211     IDENTITY(Modifier.IDENTITY, false,
212             PreviewFeatures.isEnabled() ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET,
213             new Function<ClassFileFormatVersion, Set<Location>>() {
214                 @Override
215                 public Set<Location> apply(ClassFileFormatVersion cffv) {
216                     return (cffv.compareTo(ClassFileFormatVersion.RELEASE_22) >= 0
217                             && PreviewFeatures.isEnabled())
218                             ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET;
219                 }
220             }),
221 
222     /**
223      * The module flag {@code ACC_OPEN} with a mask value of {@code
224      * 0x0020}.
225      * @see java.lang.module.ModuleDescriptor#isOpen
226      */
227     OPEN(0x0000_0020, false, Location.SET_MODULE,
228          new Function<ClassFileFormatVersion, Set<Location>>() {
229              @Override
230              public Set<Location> apply(ClassFileFormatVersion cffv) {
231                  return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
232                      Location.SET_MODULE:
233                      Location.EMPTY_SET;}
234          }),
235 
236     /**
237      * The module requires flag {@code ACC_TRANSITIVE} with a mask
238      * value of {@code 0x0020}.
239      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
240      */
241     TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
242                new Function<ClassFileFormatVersion, Set<Location>>() {
243                    @Override
244                    public Set<Location> apply(ClassFileFormatVersion cffv) {
245                        return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
246                            Location.SET_MODULE_REQUIRES:
247                            Location.EMPTY_SET;}
248                }),
249 
250     /**
251      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
252      * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
253      * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
254      */
255     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, null),
256 
257     /**
258      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
259      * value of {@code 0x0040}.
260      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
261      */
262     STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
263                  new Function<ClassFileFormatVersion, Set<Location>>() {
264                      @Override
265                      public Set<Location> apply(ClassFileFormatVersion cffv) {
266                          return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
267                              Location.SET_MODULE_REQUIRES:
268                              Location.EMPTY_SET;}
269                  }),
270 
271     /**
272      * The access flag {@code ACC_VOLATILE}, corresponding to the
273      * source modifier {@link Modifier#VOLATILE volatile}, with a mask
274      * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
275      */
276     VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, null),
277 
278     /**
279      * The access flag {@code ACC_BRIDGE} with a mask value of
280      * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
281      * @see Method#isBridge()
282      */
283     BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
284            new Function<ClassFileFormatVersion, Set<Location>>() {
285                @Override
286                public Set<Location> apply(ClassFileFormatVersion cffv) {
287                    return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
288                        Location.SET_METHOD:
289                        Location.EMPTY_SET;}
290            }),
291 

500      * given class file format version}
501      * @param cffv the class file format version to use
502      * @throws NullPointerException if the parameter is {@code null}
503      */
504     public Set<Location> locations(ClassFileFormatVersion cffv) {
505         Objects.requireNonNull(cffv);
506         if (cffvToLocations == null) {
507             return locations;
508         } else {
509             return cffvToLocations.apply(cffv);
510         }
511     }
512 
513     /**
514      * {@return an unmodifiable set of access flags for the given mask value
515      * appropriate for the location in question}
516      *
517      * @param mask bit mask of access flags
518      * @param location context to interpret mask value
519      * @throws IllegalArgumentException if the mask contains bit
520      * positions not supported for the location in question
521      */
522     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
523         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
524         for (var accessFlag : LocationToFlags.locationToFlags.get(location)) {
525             int accessMask = accessFlag.mask();
526             if ((mask & accessMask) != 0) {
527                 result.add(accessFlag);
528                 mask = mask & ~accessMask;
529                 if (mask == 0) {
530                     break;      // no more mask bits
531                 }
532             }
533         }
534         if (mask != 0) {
535             throw new IllegalArgumentException("Unmatched bit position 0x" +
536                                                Integer.toHexString(mask) +
537                                                " for location " + location);
538         }
539         return Collections.unmodifiableSet(result);
540     }
541 
542     /**
543      * {@return an unmodifiable set of access flags for the given mask value
544      * appropriate for the location in question}
545      *
546      * @param mask bit mask of access flags
547      * @param location context to interpret mask value
548      * @param cffv the class file format version
549      * @throws IllegalArgumentException if the mask contains bit
550      * positions not supported for the location in question
551      */
552     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
553                                                     ClassFileFormatVersion cffv) {
554         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
555         for (var accessFlag : AccessFlag.values()) {
556             int accessMask = accessFlag.mask();
557             if ((mask & accessMask) != 0) {
558                 var locations = accessFlag.locations(cffv);
559                 if (locations.contains(location)) {
560                     result.add(accessFlag);
561                     mask = mask & ~accessMask;
562                     if (mask == 0) {
563                         break;      // no more mask bits
564                     }
565                 }
566             }
567         }
568         if (mask != 0) {
569             throw new IllegalArgumentException("Unmatched bit position 0x" +
570                                                Integer.toHexString(mask) +
571                                                " for location " + location +
572                                                " for class file format version " + cffv);
573         }
574         return Collections.unmodifiableSet(result);
575     }
576 
577 
578     /**
579      * A location within a class file where flags can be applied.
580      *
581      * Note that since these locations represent class file structures
582      * rather than language structures many language structures, such
583      * as constructors and interfaces, are <em>not</em> present.
584      * @since 20
585      */
586     public enum Location {
587         /**
588          * Class location.
589          * @jvms 4.1 The ClassFile Structure
590          */
591         CLASS,
592 
593         /**
594          * Field location.
595          * @jvms 4.5 Fields
596          */
597         FIELD,

676               Set.of(CLASS, FIELD, METHOD,
677                      INNER_CLASS, METHOD_PARAMETER);
678         private static final Set<Location> SET_SYNTHETIC_9 =
679               // Added as an access flag in 7
680               Set.of(CLASS, FIELD, METHOD,
681                      INNER_CLASS,
682                      METHOD_PARAMETER, // Added in 8
683                      // Module-related items added in 9
684                      MODULE, MODULE_REQUIRES,
685                      MODULE_EXPORTS, MODULE_OPENS);
686         private static final Set<Location> SET_MANDATED_9 =
687             Set.of(METHOD_PARAMETER, // From 8
688                    // Starting in 9
689                    MODULE, MODULE_REQUIRES,
690                    MODULE_EXPORTS, MODULE_OPENS);
691     }
692 
693     private static class LocationToFlags {
694         private static Map<Location, Set<AccessFlag>> locationToFlags =
695             Map.ofEntries(entry(Location.CLASS,
696                                 Set.of(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER),
697                                        INTERFACE, ABSTRACT,
698                                        SYNTHETIC, ANNOTATION,
699                                        ENUM, AccessFlag.MODULE)),
700                           entry(Location.FIELD,
701                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
702                                        STATIC, FINAL, VOLATILE,
703                                        TRANSIENT, SYNTHETIC, ENUM, STRICT)),
704                           entry(Location.METHOD,
705                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
706                                        STATIC, FINAL, SYNCHRONIZED,
707                                        BRIDGE, VARARGS, NATIVE,
708                                        ABSTRACT, STRICT, SYNTHETIC)),
709                           entry(Location.INNER_CLASS,
710                                 Set.of(PUBLIC, PRIVATE, PROTECTED, IDENTITY,
711                                        STATIC, FINAL, INTERFACE, ABSTRACT,
712                                        SYNTHETIC, ANNOTATION, ENUM)),
713                           entry(Location.METHOD_PARAMETER,
714                                 Set.of(FINAL, SYNTHETIC, MANDATED)),
715                           entry(Location.MODULE,
716                                 Set.of(OPEN, SYNTHETIC, MANDATED)),
717                           entry(Location.MODULE_REQUIRES,
718                                 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
719                           entry(Location.MODULE_EXPORTS,
720                                 Set.of(SYNTHETIC, MANDATED)),
721                           entry(Location.MODULE_OPENS,
722                                 Set.of(SYNTHETIC, MANDATED)));
723     }
724 }
< prev index next >