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.lang.classfile.ClassModel;
29 import java.lang.classfile.FieldModel;
30 import java.lang.classfile.MethodModel;
31 import java.lang.classfile.attribute.InnerClassInfo;
32 import java.lang.classfile.attribute.MethodParameterInfo;
33 import java.lang.classfile.attribute.ModuleAttribute;
34 import java.lang.classfile.attribute.ModuleExportInfo;
35 import java.lang.classfile.attribute.ModuleOpenInfo;
36 import java.lang.classfile.attribute.ModuleRequireInfo;
37 import java.lang.module.ModuleDescriptor;
38 import java.util.AbstractSet;
39 import java.util.Collection;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.NoSuchElementException;
44 import java.util.Objects;
45 import java.util.Set;
46 import java.util.function.Consumer;
47 import java.util.function.Predicate;
145 STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
146 List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
147
148 /**
149 * The access flag {@code ACC_FINAL}, corresponding to the source
150 * modifier {@link Modifier#FINAL final}, with a mask
151 * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
152 */
153 FINAL(Modifier.FINAL, true,
154 Location.SET_FINAL_8,
155 List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
156 Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
157
158 /**
159 * The access flag {@code ACC_SUPER} with a mask value of {@code
160 * 0x0020}.
161 *
162 * @apiNote
163 * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
164 * flag as set in every class file (JVMS {@jvms 4.1}).
165 */
166 SUPER(0x0000_0020, false, Location.SET_CLASS, List.of()),
167
168 /**
169 * The module flag {@code ACC_OPEN} with a mask value of {@code
170 * 0x0020}.
171 * @see java.lang.module.ModuleDescriptor#isOpen
172 */
173 OPEN(0x0000_0020, false, Location.SET_MODULE,
174 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
175
176 /**
177 * The module requires flag {@code ACC_TRANSITIVE} with a mask
178 * value of {@code 0x0020}.
179 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
180 */
181 TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
182 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
183
184 /**
185 * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
186 * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
247 * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
248 */
249 ABSTRACT(Modifier.ABSTRACT, true,
250 Location.SET_CLASS_METHOD_INNER_CLASS,
251 List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
252
253 /**
254 * The access flag {@code ACC_STRICT}, corresponding to the source
255 * modifier {@link Modifier#STRICT strictfp}, with a mask value of
256 * <code>{@value "0x%04x" Modifier#STRICT}</code>.
257 *
258 * @apiNote
259 * The {@code ACC_STRICT} access flag is defined for class file
260 * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
261 * corresponding to Java SE 1.2 through 16.
262 */
263 STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
264 List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
265 Map.entry(RELEASE_1, Location.EMPTY_SET))),
266
267 /**
268 * The access flag {@code ACC_SYNTHETIC} with a mask value of
269 * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
270 * @see Class#isSynthetic()
271 * @see Executable#isSynthetic()
272 * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
273 */
274 SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
275 List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
276 Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
277 Map.entry(RELEASE_4, Location.EMPTY_SET))),
278
279 /**
280 * The access flag {@code ACC_ANNOTATION} with a mask value of
281 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
282 * @see Class#isAnnotation()
283 */
284 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
285 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
286
360 * {@return locations this flag can be applied to in the given class file
361 * format version}
362 * <p>
363 * This method returns an empty set if this flag is not defined in
364 * the given {@code cffv}.
365 *
366 * @param cffv the class file format version to use
367 * @throws NullPointerException if the parameter is {@code null}
368 */
369 public Set<Location> locations(ClassFileFormatVersion cffv) {
370 return Location.findInHistory(locations, historicalLocations, cffv);
371 }
372
373 /**
374 * {@return an unmodifiable set of access flags for the given mask value
375 * appropriate for the location in question}
376 *
377 * @param mask bit mask of access flags
378 * @param location context to interpret mask value
379 * @throws IllegalArgumentException if the mask contains bit
380 * positions not support for the location in question
381 */
382 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
383 var definition = findDefinition(location);
384 int flagsMask = location.flagsMask();
385 int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
386 int unmatchedMask = mask & (~parsingMask);
387 if (unmatchedMask != 0) {
388 throw new IllegalArgumentException("Unmatched bit position 0x" +
389 Integer.toHexString(unmatchedMask) +
390 " for location " + location);
391 }
392 return new AccessFlagSet(definition, mask);
393 }
394
395 /**
396 * A location within a {@code class} file where flags can be applied.
397 * <p>
398 * Note that since these locations represent {@code class} file structures
399 * rather than language structures, many language structures, such
400 * as constructors and interfaces, are <em>not</em> present.
401 * @since 20
402 */
403 public enum Location {
404 /**
405 * Class location.
406 *
407 * @see Class#accessFlags()
408 * @see ClassModel#flags()
409 * @see Modifier#classModifiers()
410 * @see Modifier#interfaceModifiers()
411 * @jvms 4.1 The {@code ClassFile} Structure
412 */
413 CLASS(ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
414 ACC_INTERFACE | ACC_ABSTRACT |
415 ACC_SYNTHETIC | ACC_ANNOTATION |
416 ACC_ENUM | ACC_MODULE,
417 List.of(Map.entry(RELEASE_8, // no module
418 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
419 ACC_INTERFACE | ACC_ABSTRACT |
420 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
421 Map.entry(RELEASE_4, // no synthetic, annotation, enum
422 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
423 ACC_INTERFACE | ACC_ABSTRACT))),
424
425 /**
426 * Field location.
427 *
428 * @see Field#accessFlags()
429 * @see FieldModel#flags()
430 * @see Modifier#fieldModifiers()
431 * @jvms 4.5 Fields
432 */
433 FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
434 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
435 ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM,
436 List.of(Map.entry(RELEASE_4, // no synthetic, enum
437 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
438 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
439 ACC_TRANSIENT))),
440
441 /**
442 * Method location.
443 *
444 * @see Executable#accessFlags()
445 * @see MethodModel#flags()
446 * @see Modifier#methodModifiers()
447 * @see Modifier#constructorModifiers()
448 * @jvms 4.6 Methods
449 */
450 METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
451 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
452 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
453 ACC_ABSTRACT | ACC_SYNTHETIC,
454 List.of(Map.entry(RELEASE_16, // had strict
455 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
457 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
458 ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
459 Map.entry(RELEASE_4, // no bridge, varargs, synthetic
460 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
461 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
462 ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
463 Map.entry(RELEASE_1, // no strict
464 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
465 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
466 ACC_NATIVE | ACC_ABSTRACT))),
467
468 /**
469 * Inner class location.
470 *
471 * @see Class#accessFlags()
472 * @see InnerClassInfo#flags()
473 * @see Modifier#classModifiers()
474 * @see Modifier#interfaceModifiers()
475 * @jvms 4.7.6 The {@code InnerClasses} Attribute
476 */
477 INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
478 ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
479 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
480 List.of(Map.entry(RELEASE_4, // no synthetic, annotation, enum
481 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
482 ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
483 ACC_ABSTRACT),
484 Map.entry(RELEASE_0, 0))), // did not exist
485
486 /**
487 * Method parameter location.
488 *
489 * @see Parameter#accessFlags()
490 * @see MethodParameterInfo#flags()
491 * @see Modifier#parameterModifiers()
492 * @jvms 4.7.24 The {@code MethodParameters} Attribute
493 */
494 METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
495 List.of(Map.entry(RELEASE_7, 0))), // did not exist
496
497 /**
673 * @throws NullPointerException if {@code cffv} is {@code null}
674 * @since 25
675 */
676 public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
677 // implicit null check cffv
678 return new AccessFlagSet(findDefinition(this), flagsMask(cffv));
679 }
680 }
681
682 private static AccessFlag[] createDefinition(AccessFlag... known) {
683 var ret = new AccessFlag[Character.SIZE];
684 for (var flag : known) {
685 var mask = flag.mask;
686 int pos = Integer.numberOfTrailingZeros(mask);
687 assert ret[pos] == null : ret[pos] + " " + flag;
688 ret[pos] = flag;
689 }
690 return ret;
691 }
692
693 // Will take extra args in the future for valhalla switch
694 private static AccessFlag[] findDefinition(Location location) {
695 return switch (location) {
696 case CLASS -> CLASS_FLAGS;
697 case FIELD -> FIELD_FLAGS;
698 case METHOD -> METHOD_FLAGS;
699 case INNER_CLASS -> INNER_CLASS_FLAGS;
700 case METHOD_PARAMETER -> METHOD_PARAMETER_FLAGS;
701 case MODULE -> MODULE_FLAGS;
702 case MODULE_REQUIRES -> MODULE_REQUIRES_FLAGS;
703 case MODULE_EXPORTS -> MODULE_EXPORTS_FLAGS;
704 case MODULE_OPENS -> MODULE_OPENS_FLAGS;
705 };
706 }
707
708 private static final @Stable AccessFlag[] // Can use stable array and lazy init in the future
709 CLASS_FLAGS = createDefinition(PUBLIC, FINAL, SUPER, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
710 FIELD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM),
711 METHOD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, BRIDGE, VARARGS, NATIVE, ABSTRACT, STRICT, SYNTHETIC),
712 INNER_CLASS_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),
713 METHOD_PARAMETER_FLAGS = createDefinition(FINAL, SYNTHETIC, MANDATED),
714 MODULE_FLAGS = createDefinition(OPEN, SYNTHETIC, MANDATED),
715 MODULE_REQUIRES_FLAGS = createDefinition(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED),
716 MODULE_EXPORTS_FLAGS = createDefinition(SYNTHETIC, MANDATED),
717 MODULE_OPENS_FLAGS = createDefinition(SYNTHETIC, MANDATED);
718
719 private static int undefinedMask(AccessFlag[] definition, int mask) {
720 assert definition.length == Character.SIZE;
721 int definedMask = 0;
722 for (int i = 0; i < Character.SIZE; i++) {
723 if (definition[i] != null) {
724 definedMask |= 1 << i;
725 }
726 }
727 return mask & ~definedMask;
728 }
729
730 private static final class AccessFlagSet extends AbstractSet<AccessFlag> {
731 private final @Stable AccessFlag[] definition;
732 private final int mask;
|
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.lang.classfile.ClassModel;
32 import java.lang.classfile.FieldModel;
33 import java.lang.classfile.MethodModel;
34 import java.lang.classfile.attribute.InnerClassInfo;
35 import java.lang.classfile.attribute.MethodParameterInfo;
36 import java.lang.classfile.attribute.ModuleAttribute;
37 import java.lang.classfile.attribute.ModuleExportInfo;
38 import java.lang.classfile.attribute.ModuleOpenInfo;
39 import java.lang.classfile.attribute.ModuleRequireInfo;
40 import java.lang.module.ModuleDescriptor;
41 import java.util.AbstractSet;
42 import java.util.Collection;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.NoSuchElementException;
47 import java.util.Objects;
48 import java.util.Set;
49 import java.util.function.Consumer;
50 import java.util.function.Predicate;
148 STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
149 List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
150
151 /**
152 * The access flag {@code ACC_FINAL}, corresponding to the source
153 * modifier {@link Modifier#FINAL final}, with a mask
154 * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
155 */
156 FINAL(Modifier.FINAL, true,
157 Location.SET_FINAL_8,
158 List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
159 Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
160
161 /**
162 * The access flag {@code ACC_SUPER} with a mask value of {@code
163 * 0x0020}.
164 *
165 * @apiNote
166 * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
167 * flag as set in every class file (JVMS {@jvms 4.1}).
168 * If preview feature is enabled,
169 * the {@code 0x0020} access flag bit is {@linkplain #IDENTITY IDENTITY access flag}.
170 */
171 SUPER(0x0000_0020, false,
172 PreviewFeatures.isEnabled() ? Location.EMPTY_SET : Location.SET_CLASS,
173 List.of()),
174
175 /**
176 * The access flag {@code ACC_IDENTITY}, corresponding to the
177 * modifier {@link Modifier#IDENTITY identity}, with a mask
178 * value of <code>{@value "0x%04x" Modifier#IDENTITY}</code>.
179 * @jvms 4.1 -B. Class access and property modifiers
180 *
181 * @since Valhalla
182 */
183 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
184 IDENTITY(Modifier.IDENTITY, false,
185 PreviewFeatures.isEnabled() ? Location.SET_CLASS_INNER_CLASS : Location.EMPTY_SET,
186 List.of()),
187
188 /**
189 * The module flag {@code ACC_OPEN} with a mask value of {@code
190 * 0x0020}.
191 * @see java.lang.module.ModuleDescriptor#isOpen
192 */
193 OPEN(0x0000_0020, false, Location.SET_MODULE,
194 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
195
196 /**
197 * The module requires flag {@code ACC_TRANSITIVE} with a mask
198 * value of {@code 0x0020}.
199 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
200 */
201 TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
202 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
203
204 /**
205 * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
206 * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
267 * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
268 */
269 ABSTRACT(Modifier.ABSTRACT, true,
270 Location.SET_CLASS_METHOD_INNER_CLASS,
271 List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
272
273 /**
274 * The access flag {@code ACC_STRICT}, corresponding to the source
275 * modifier {@link Modifier#STRICT strictfp}, with a mask value of
276 * <code>{@value "0x%04x" Modifier#STRICT}</code>.
277 *
278 * @apiNote
279 * The {@code ACC_STRICT} access flag is defined for class file
280 * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
281 * corresponding to Java SE 1.2 through 16.
282 */
283 STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
284 List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
285 Map.entry(RELEASE_1, Location.EMPTY_SET))),
286
287 /**
288 * The access flag {@code ACC_STRICT_INIT}, with a mask
289 * value of {@code 0x0800}.
290 *
291 * @jvms 4.5 Fields
292 * @since Valhalla
293 */
294 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
295 STRICT_INIT(Modifier.STRICT, false,
296 PreviewFeatures.isEnabled() ? Location.SET_FIELD : Location.EMPTY_SET,
297 List.of()),
298
299 /**
300 * The access flag {@code ACC_SYNTHETIC} with a mask value of
301 * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
302 * @see Class#isSynthetic()
303 * @see Executable#isSynthetic()
304 * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
305 */
306 SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
307 List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
308 Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
309 Map.entry(RELEASE_4, Location.EMPTY_SET))),
310
311 /**
312 * The access flag {@code ACC_ANNOTATION} with a mask value of
313 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
314 * @see Class#isAnnotation()
315 */
316 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
317 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
318
392 * {@return locations this flag can be applied to in the given class file
393 * format version}
394 * <p>
395 * This method returns an empty set if this flag is not defined in
396 * the given {@code cffv}.
397 *
398 * @param cffv the class file format version to use
399 * @throws NullPointerException if the parameter is {@code null}
400 */
401 public Set<Location> locations(ClassFileFormatVersion cffv) {
402 return Location.findInHistory(locations, historicalLocations, cffv);
403 }
404
405 /**
406 * {@return an unmodifiable set of access flags for the given mask value
407 * appropriate for the location in question}
408 *
409 * @param mask bit mask of access flags
410 * @param location context to interpret mask value
411 * @throws IllegalArgumentException if the mask contains bit
412 * positions not supported for the location in question
413 */
414 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
415 var definition = findDefinition(location);
416 int flagsMask = location.flagsMask();
417 int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
418 int unmatchedMask = mask & (~parsingMask);
419 if (unmatchedMask != 0) {
420 throw new IllegalArgumentException("Unmatched bit position 0x" +
421 Integer.toHexString(unmatchedMask) +
422 " for location " + location);
423 }
424 return new AccessFlagSet(definition, mask);
425 }
426
427 /**
428 * {@return an unmodifiable set of access flags for the given mask value
429 * appropriate for the location in question}
430 *
431 * @param mask bit mask of access flags
432 * @param location context to interpret mask value
433 * @param cffv the class file format version
434 * @throws IllegalArgumentException if the mask contains bit
435 * positions not supported for the location in question
436 *
437 * @since Valhalla
438 */
439 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location,
440 ClassFileFormatVersion cffv) {
441 var definition = findDefinition(location);
442 int flagsMask = location.flagsMask(cffv);
443 int parsingMask = location == Location.METHOD ? flagsMask | ACC_STRICT : flagsMask; // flagMask lacks strictfp
444 int unmatchedMask = mask & (~parsingMask);
445 if (unmatchedMask != 0) {
446 throw new IllegalArgumentException("Unmatched bit position 0x" +
447 Integer.toHexString(unmatchedMask) +
448 " for location " + location);
449 }
450 return new AccessFlagSet(definition, mask);
451 }
452
453 /**
454 * A location within a {@code class} file where flags can be applied.
455 * <p>
456 * Note that since these locations represent {@code class} file structures
457 * rather than language structures, many language structures, such
458 * as constructors and interfaces, are <em>not</em> present.
459 * @since 20
460 */
461 public enum Location {
462 /**
463 * Class location.
464 *
465 * @see Class#accessFlags()
466 * @see ClassModel#flags()
467 * @see Modifier#classModifiers()
468 * @see Modifier#interfaceModifiers()
469 * @jvms 4.1 The {@code ClassFile} Structure
470 */
471 CLASS(ACC_PUBLIC | ACC_FINAL | (PreviewFeatures.isEnabled() ? ACC_IDENTITY : ACC_SUPER) |
472 ACC_INTERFACE | ACC_ABSTRACT |
473 ACC_SYNTHETIC | ACC_ANNOTATION |
474 ACC_ENUM | ACC_MODULE,
475 List.of(Map.entry(RELEASE_8, // no module
476 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
477 ACC_INTERFACE | ACC_ABSTRACT |
478 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
479 Map.entry(RELEASE_4, // no synthetic, annotation, enum
480 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
481 ACC_INTERFACE | ACC_ABSTRACT))),
482
483 /**
484 * Field location.
485 *
486 * @see Field#accessFlags()
487 * @see FieldModel#flags()
488 * @see Modifier#fieldModifiers()
489 * @jvms 4.5 Fields
490 */
491 FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
492 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
493 ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | (PreviewFeatures.isEnabled() ? ACC_STRICT : 0),
494 List.of(Map.entry(RELEASE_4, // no synthetic, enum
495 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
496 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
497 ACC_TRANSIENT))),
498
499 /**
500 * Method location.
501 *
502 * @see Executable#accessFlags()
503 * @see MethodModel#flags()
504 * @see Modifier#methodModifiers()
505 * @see Modifier#constructorModifiers()
506 * @jvms 4.6 Methods
507 */
508 METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
509 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
510 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
511 ACC_ABSTRACT | ACC_SYNTHETIC,
512 List.of(Map.entry(RELEASE_16, // had strict
513 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
515 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
516 ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
517 Map.entry(RELEASE_4, // no bridge, varargs, synthetic
518 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
519 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
520 ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
521 Map.entry(RELEASE_1, // no strict
522 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
523 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
524 ACC_NATIVE | ACC_ABSTRACT))),
525
526 /**
527 * Inner class location.
528 *
529 * @see Class#accessFlags()
530 * @see InnerClassInfo#flags()
531 * @see Modifier#classModifiers()
532 * @see Modifier#interfaceModifiers()
533 * @jvms 4.7.6 The {@code InnerClasses} Attribute
534 */
535 INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | (PreviewFeatures.isEnabled() ? ACC_IDENTITY : 0) |
536 ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
537 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
538 List.of(Map.entry(RELEASE_4, // no synthetic, annotation, enum
539 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
540 ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
541 ACC_ABSTRACT),
542 Map.entry(RELEASE_0, 0))), // did not exist
543
544 /**
545 * Method parameter location.
546 *
547 * @see Parameter#accessFlags()
548 * @see MethodParameterInfo#flags()
549 * @see Modifier#parameterModifiers()
550 * @jvms 4.7.24 The {@code MethodParameters} Attribute
551 */
552 METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
553 List.of(Map.entry(RELEASE_7, 0))), // did not exist
554
555 /**
731 * @throws NullPointerException if {@code cffv} is {@code null}
732 * @since 25
733 */
734 public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
735 // implicit null check cffv
736 return new AccessFlagSet(findDefinition(this), flagsMask(cffv));
737 }
738 }
739
740 private static AccessFlag[] createDefinition(AccessFlag... known) {
741 var ret = new AccessFlag[Character.SIZE];
742 for (var flag : known) {
743 var mask = flag.mask;
744 int pos = Integer.numberOfTrailingZeros(mask);
745 assert ret[pos] == null : ret[pos] + " " + flag;
746 ret[pos] = flag;
747 }
748 return ret;
749 }
750
751 private static AccessFlag[] findDefinition(Location location) {
752 return switch (location) {
753 case CLASS -> CLASS_FLAGS;
754 case FIELD -> FIELD_FLAGS;
755 case METHOD -> METHOD_FLAGS;
756 case INNER_CLASS -> INNER_CLASS_FLAGS;
757 case METHOD_PARAMETER -> METHOD_PARAMETER_FLAGS;
758 case MODULE -> MODULE_FLAGS;
759 case MODULE_REQUIRES -> MODULE_REQUIRES_FLAGS;
760 case MODULE_EXPORTS -> MODULE_EXPORTS_FLAGS;
761 case MODULE_OPENS -> MODULE_OPENS_FLAGS;
762 };
763 }
764
765 private static final @Stable AccessFlag[] // Can use stable array and lazy init in the future
766 CLASS_FLAGS = createDefinition(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
767 FIELD_FLAGS = PreviewFeatures.isEnabled() ? // Using Valhalla
768 createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT) :
769 createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM),
770 METHOD_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SYNCHRONIZED, BRIDGE, VARARGS, NATIVE, ABSTRACT, STRICT, SYNTHETIC),
771 INNER_CLASS_FLAGS = createDefinition(PUBLIC, PRIVATE, PROTECTED, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM),
772 METHOD_PARAMETER_FLAGS = createDefinition(FINAL, SYNTHETIC, MANDATED),
773 MODULE_FLAGS = createDefinition(OPEN, SYNTHETIC, MANDATED),
774 MODULE_REQUIRES_FLAGS = createDefinition(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED),
775 MODULE_EXPORTS_FLAGS = createDefinition(SYNTHETIC, MANDATED),
776 MODULE_OPENS_FLAGS = createDefinition(SYNTHETIC, MANDATED);
777
778 private static int undefinedMask(AccessFlag[] definition, int mask) {
779 assert definition.length == Character.SIZE;
780 int definedMask = 0;
781 for (int i = 0; i < Character.SIZE; i++) {
782 if (definition[i] != null) {
783 definedMask |= 1 << i;
784 }
785 }
786 return mask & ~definedMask;
787 }
788
789 private static final class AccessFlagSet extends AbstractSet<AccessFlag> {
790 private final @Stable AccessFlag[] definition;
791 private final int mask;
|