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