1 /*
2 * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.reflect;
27
28 import jdk.internal.javac.PreviewFeature;
29 import jdk.internal.reflect.AccessFlagSet;
30
31 import java.lang.classfile.ClassFile;
32 import java.lang.classfile.ClassModel;
33 import java.lang.classfile.FieldModel;
34 import java.lang.classfile.MethodModel;
35 import java.lang.classfile.attribute.InnerClassInfo;
36 import java.lang.classfile.attribute.MethodParameterInfo;
37 import java.lang.classfile.attribute.ModuleAttribute;
38 import java.lang.classfile.attribute.ModuleExportInfo;
39 import java.lang.classfile.attribute.ModuleOpenInfo;
40 import java.lang.classfile.attribute.ModuleRequireInfo;
41 import java.lang.module.ModuleDescriptor;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Objects;
45 import java.util.Set;
46
47 import static java.lang.classfile.ClassFile.*;
48 import static java.lang.reflect.ClassFileFormatVersion.*;
49
50 /**
51 * Represents a JVM access or module-related flag on a runtime member,
52 * such as a {@linkplain Class class}, {@linkplain Field field}, or
53 * {@linkplain Executable method}.
54 *
55 * <P>JVM access and module-related flags are related to, but distinct
56 * from Java language {@linkplain Modifier modifiers}. Some modifiers
57 * and access flags have a one-to-one correspondence, such as {@code
58 * public}. In other cases, some language-level modifiers do
59 * <em>not</em> have an access flag, such as {@code sealed} (JVMS
60 * {@jvms 4.7.31}) and some access flags have no corresponding
61 * modifier, such as {@linkplain #SYNTHETIC synthetic}.
62 *
63 * <p>The values for the constants representing the access and module
64 * flags are taken from sections of <cite>The Java Virtual Machine
65 * Specification</cite> including {@jvms 4.1} (class access and
66 * property modifiers), {@jvms 4.5} (field access and property flags),
67 * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
68 * (nested class access and property flags), {@jvms 4.7.24} (method
69 * parameters), and {@jvms 4.7.25} (module flags and requires,
70 * exports, and opens flags).
71 *
72 * <p>The {@linkplain #mask() mask} values for the different access
73 * flags are <em>not</em> distinct. Flags are defined for different
74 * kinds of JVM structures and the same bit position has different
75 * meanings in different contexts. For example, {@code 0x0000_0040}
76 * indicates a {@link #VOLATILE volatile} field but a {@linkplain
77 * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
78 * #TRANSIENT transient} field but a {@linkplain #VARARGS variable
79 * arity (varargs)} method.
80 *
81 * @implSpec
82 * The access flag constants are ordered by non-decreasing mask
83 * value; that is the mask value of a constant is greater than or
84 * equal to the mask value of an immediate neighbor to its (syntactic)
85 * left. If new constants are added, this property will be
86 * maintained. That implies new constants will not necessarily be
87 * added at the end of the existing list.
88 *
89 * @apiNote
90 * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new
91 * {@linkplain Runtime.Version#feature() feature release}. A new class
92 * file version may define new access flags or retire old ones. {@code
93 * AccessFlag} is intended to model the set of access flags across
94 * class file format versions. The range of versions an access flag is
95 * recognized is not explicitly indicated in this API. See the current
96 * <cite>The Java Virtual Machine Specification</cite> for
97 * details. Unless otherwise indicated, access flags can be assumed to
98 * be recognized in the {@linkplain Runtime#version() current
99 * version}.
100 *
101 * @see java.lang.reflect.Modifier
102 * @see java.lang.module.ModuleDescriptor.Modifier
103 * @see java.lang.module.ModuleDescriptor.Requires.Modifier
104 * @see java.lang.module.ModuleDescriptor.Exports.Modifier
105 * @see java.lang.module.ModuleDescriptor.Opens.Modifier
106 * @see java.compiler/javax.lang.model.element.Modifier
107 * @since 20
108 */
109 @SuppressWarnings("doclint:reference") // cross-module link
110 public enum AccessFlag {
111 /**
112 * The access flag {@code ACC_PUBLIC}, corresponding to the source
113 * modifier {@link Modifier#PUBLIC public}, with a mask value of
114 * <code>{@value "0x%04x" Modifier#PUBLIC}</code>.
115 */
116 PUBLIC(Modifier.PUBLIC, true,
117 Location.SET_CLASS_FIELD_METHOD_INNER_CLASS,
118 List.of(Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
119
120 /**
121 * The access flag {@code ACC_PRIVATE}, corresponding to the
122 * source modifier {@link Modifier#PRIVATE private}, with a mask
123 * value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>.
124 */
125 PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS,
126 List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
127
128 /**
129 * The access flag {@code ACC_PROTECTED}, corresponding to the
130 * source modifier {@link Modifier#PROTECTED protected}, with a mask
131 * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>.
132 */
133 PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS,
134 List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
135
136 /**
137 * The access flag {@code ACC_STATIC}, corresponding to the source
138 * modifier {@link Modifier#STATIC static}, with a mask value of
139 * <code>{@value "0x%04x" Modifier#STATIC}</code>.
140 */
141 STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
142 List.of(Map.entry(RELEASE_0, Location.SET_FIELD_METHOD))),
143
144 /**
145 * The access flag {@code ACC_FINAL}, corresponding to the source
146 * modifier {@link Modifier#FINAL final}, with a mask
147 * value of <code>{@value "0x%04x" Modifier#FINAL}</code>.
148 */
149 FINAL(Modifier.FINAL, true,
150 Location.SET_FINAL_8,
151 List.of(Map.entry(RELEASE_7, Location.SET_CLASS_FIELD_METHOD_INNER_CLASS),
152 Map.entry(RELEASE_0, Location.SET_CLASS_FIELD_METHOD))),
153
154 /**
155 * The access flag {@code ACC_SUPER} with a mask value of {@code
156 * 0x0020}.
157 *
158 * @apiNote
159 * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
160 * flag as set in every class file (JVMS {@jvms 4.1}).
161 * If preview feature is enabled,
162 * the {@code 0x0020} access flag bit is {@linkplain #IDENTITY IDENTITY access flag}.
163 */
164 SUPER(0x0000_0020, false,
165 Location.SET_CLASS,
166 List.of()),
167
168 /**
169 * The access flag {@code ACC_IDENTITY} with a mask value of
170 * <code>{@value "0x%04x" ClassFile#ACC_IDENTITY}</code>.
171 * <p>
172 * If a class does not use preview features, the {@code ACC_IDENTITY} flag
173 * is considered always set for that class; if an interface or module
174 * descriptor does not use preview features, the {@code ACC_IDENTITY} flag
175 * is considered not set for that interface or module descriptor.
176 *
177 * @see Class#isValue()
178 * @jvms value-objects-4.1 Class access and property modifiers
179 * @since 28
180 */
181 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
182 IDENTITY(ACC_IDENTITY, false,
183 Location.EMPTY_SET,
184 List.of()),
185
186 /**
187 * The module flag {@code ACC_OPEN} with a mask value of {@code
188 * 0x0020}.
189 * @see java.lang.module.ModuleDescriptor#isOpen
190 */
191 OPEN(0x0000_0020, false, Location.SET_MODULE,
192 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
193
194 /**
195 * The module requires flag {@code ACC_TRANSITIVE} with a mask
196 * value of {@code 0x0020}.
197 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
198 */
199 TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
200 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
201
202 /**
203 * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
204 * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with
205 * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>.
206 */
207 SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, List.of()),
208
209 /**
210 * The module requires flag {@code ACC_STATIC_PHASE} with a mask
211 * value of {@code 0x0040}.
212 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
213 */
214 STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
215 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
216
217 /**
218 * The access flag {@code ACC_VOLATILE}, corresponding to the
219 * source modifier {@link Modifier#VOLATILE volatile}, with a mask
220 * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>.
221 */
222 VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, List.of()),
223
224 /**
225 * The access flag {@code ACC_BRIDGE} with a mask value of
226 * <code>{@value "0x%04x" Modifier#BRIDGE}</code>
227 * @see Method#isBridge()
228 */
229 BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
230 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
231
232 /**
233 * The access flag {@code ACC_TRANSIENT}, corresponding to the
234 * source modifier {@link Modifier#TRANSIENT transient}, with a
235 * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>.
236 */
237 TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, List.of()),
238
239 /**
240 * The access flag {@code ACC_VARARGS} with a mask value of
241 * <code>{@value "0x%04x" Modifier#VARARGS}</code>.
242 * @see Executable#isVarArgs()
243 */
244 VARARGS(Modifier.VARARGS, false, Location.SET_METHOD,
245 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
246
247 /**
248 * The access flag {@code ACC_NATIVE}, corresponding to the source
249 * modifier {@link Modifier#NATIVE native}, with a mask value of
250 * <code>{@value "0x%04x" Modifier#NATIVE}</code>.
251 */
252 NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, List.of()),
253
254 /**
255 * The access flag {@code ACC_INTERFACE} with a mask value of
256 * {@code 0x0200}.
257 * @see Class#isInterface()
258 */
259 INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS,
260 List.of(Map.entry(RELEASE_0, Location.SET_CLASS))),
261
262 /**
263 * The access flag {@code ACC_ABSTRACT}, corresponding to the
264 * source modifier {@link Modifier#ABSTRACT abstract}, with a mask
265 * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>.
266 */
267 ABSTRACT(Modifier.ABSTRACT, true,
268 Location.SET_CLASS_METHOD_INNER_CLASS,
269 List.of(Map.entry(RELEASE_0, Location.SET_CLASS_METHOD))),
270
271 /**
272 * The access flag {@code ACC_STRICT}, corresponding to the source
273 * modifier {@link Modifier#STRICT strictfp}, with a mask value of
274 * <code>{@value "0x%04x" Modifier#STRICT}</code>.
275 *
276 * @apiNote
277 * The {@code ACC_STRICT} access flag is defined for class file
278 * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
279 * corresponding to Java SE 1.2 through 16.
280 */
281 STRICT(Modifier.STRICT, true, Location.EMPTY_SET,
282 List.of(Map.entry(RELEASE_16, Location.SET_METHOD),
283 Map.entry(RELEASE_1, Location.EMPTY_SET))),
284
285 /**
286 * The access flag {@code ACC_STRICT_INIT}, with a mask value of
287 * <code>{@value "0x%04x" ClassFile#ACC_STRICT_INIT}</code>.
288 *
289 * <p>The {@code ACC_STRICT_INIT} flag is considered not set for a field
290 * declared in a class or interface that does not use preview features.
291 *
292 * @see Field#isStrictInit()
293 * @jvms strict-fields-4.5 Field access and property flags
294 * @since 28
295 */
296 @PreviewFeature(feature = PreviewFeature.Feature.STRICT_FIELDS, reflective=true)
297 STRICT_INIT(ACC_STRICT_INIT, false,
298 Location.EMPTY_SET,
299 List.of()),
300
301 /**
302 * The access flag {@code ACC_SYNTHETIC} with a mask value of
303 * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>.
304 * @see Class#isSynthetic()
305 * @see Executable#isSynthetic()
306 * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
307 */
308 SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
309 List.of(Map.entry(RELEASE_8, Location.SET_SYNTHETIC_8),
310 Map.entry(RELEASE_7, Location.SET_SYNTHETIC_5),
311 Map.entry(RELEASE_4, Location.EMPTY_SET))),
312
313 /**
314 * The access flag {@code ACC_ANNOTATION} with a mask value of
315 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>.
316 * @see Class#isAnnotation()
317 */
318 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
319 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
320
321 /**
322 * The access flag {@code ACC_ENUM} with a mask value of
323 * <code>{@value "0x%04x" Modifier#ENUM}</code>.
324 * @see Class#isEnum()
325 */
326 ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS,
327 List.of(Map.entry(RELEASE_4, Location.EMPTY_SET))),
328
329 /**
330 * The access flag {@code ACC_MANDATED} with a mask value of
331 * <code>{@value "0x%04x" Modifier#MANDATED}</code>.
332 */
333 MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9,
334 List.of(Map.entry(RELEASE_8, Location.SET_METHOD_PARAM),
335 Map.entry(RELEASE_7, Location.EMPTY_SET))),
336
337 /**
338 * The access flag {@code ACC_MODULE} with a mask value of {@code
339 * 0x8000}.
340 */
341 MODULE(0x0000_8000, false, Location.SET_CLASS,
342 List.of(Map.entry(RELEASE_8, Location.EMPTY_SET))),
343 ;
344
345 // May want to override toString for a different enum constant ->
346 // name mapping.
347
348 private final int mask;
349 private final boolean sourceModifier;
350
351 // immutable
352 private final Set<Location> locations;
353 // historical locations up to a given version; immutable
354 private final List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations;
355
356 private AccessFlag(int mask,
357 boolean sourceModifier,
358 Set<Location> locations,
359 List<Map.Entry<ClassFileFormatVersion, Set<Location>>> historicalLocations) {
360 this.mask = mask;
361 this.sourceModifier = sourceModifier;
362 this.locations = locations;
363 this.historicalLocations = Location.ensureHistoryOrdered(historicalLocations);
364 }
365
366 /**
367 * {@return the corresponding mask for the access flag} The mask has
368 * exactly one bit set and is in the range of {@code char}.
369 */
370 public int mask() {
371 return mask;
372 }
373
374 /**
375 * {@return whether or not this flag has a directly corresponding
376 * modifier in the Java programming language}
377 */
378 public boolean sourceModifier() {
379 return sourceModifier;
380 }
381
382 /**
383 * {@return locations this flag can be applied to in the current class file
384 * format version}
385 * <p>
386 * This method returns an empty set if this flag is not defined in
387 * the current class file format version.
388 */
389 public Set<Location> locations() {
390 return locations(latest());
391 }
392
393 /**
394 * {@return locations this flag can be applied to in the given class file
395 * format version}
396 * <p>
397 * This method returns an empty set if this flag is not defined in
398 * the given {@code cffv}.
399 *
400 * @param cffv the class file format version to use
401 * @throws NullPointerException if the parameter is {@code null}
402 */
403 public Set<Location> locations(ClassFileFormatVersion cffv) {
404 return Location.findInHistory(locations, historicalLocations, cffv);
405 }
406
407 /**
408 * {@return an unmodifiable set of access flags for the given mask value
409 * appropriate for the location in the current class file format version}
410 *
411 * @param mask bit mask of access flags
412 * @param location context to interpret mask value
413 * @throws IllegalArgumentException if the mask contains bit
414 * positions not defined for the location in the current class file format
415 * @throws NullPointerException if {@code location} is {@code null}
416 */
417 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
418 return maskToAccessFlags(mask, location, latest());
419 }
420
421 /**
422 * {@return an unmodifiable set of access flags for the given mask value
423 * appropriate for the location in the given class file format version}
424 *
425 * @param mask bit mask of access flags
426 * @param location context to interpret mask value
427 * @param cffv the class file format to interpret mask value
428 * @throws IllegalArgumentException if the mask contains bit
429 * positions not defined for the location in the given class file format
430 * @throws NullPointerException if {@code location} or {@code cffv} is {@code null}
431 * @since 25
432 */
433 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location, ClassFileFormatVersion cffv) {
434 var definition = AccessFlagSet.findDefinition(location, cffv); // null checks location
435 int unmatchedMask = mask & (~location.flagsMask(cffv));
436 if (unmatchedMask != 0) {
437 throw new IllegalArgumentException("Unmatched bit position 0x" +
438 Integer.toHexString(unmatchedMask) +
439 " for location " + location +
440 " for class file format " + cffv);
441 }
442 return AccessFlagSet.ofValidated(definition, mask);
443 }
444
445 /**
446 * A location within a {@code class} file where flags can be applied.
447 * <p>
448 * Note that since these locations represent {@code class} file structures
449 * rather than language structures, many language structures, such
450 * as constructors and interfaces, are <em>not</em> present.
451 * @since 20
452 */
453 public enum Location {
454 /**
455 * Class location.
456 *
457 * @see Class#accessFlags()
458 * @see ClassModel#flags()
459 * @jvms 4.1 The {@code ClassFile} Structure
460 */
461 CLASS(ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
462 ACC_INTERFACE | ACC_ABSTRACT |
463 ACC_SYNTHETIC | ACC_ANNOTATION |
464 ACC_ENUM | ACC_MODULE,
465 List.of(Map.entry(RELEASE_8, // no module
466 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
467 ACC_INTERFACE | ACC_ABSTRACT |
468 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
469 Map.entry(RELEASE_4, // no synthetic, annotation, enum
470 ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
471 ACC_INTERFACE | ACC_ABSTRACT))),
472
473 /**
474 * Field location.
475 *
476 * @see Field#accessFlags()
477 * @see FieldModel#flags()
478 * @jvms 4.5 Fields
479 */
480 FIELD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
481 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
482 ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM,
483 List.of(Map.entry(RELEASE_4, // no synthetic, enum
484 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
485 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
486 ACC_TRANSIENT))),
487
488 /**
489 * Method location.
490 *
491 * @see Executable#accessFlags()
492 * @see MethodModel#flags()
493 * @jvms 4.6 Methods
494 */
495 METHOD(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
496 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
497 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
498 ACC_ABSTRACT | ACC_SYNTHETIC,
499 List.of(Map.entry(RELEASE_16, // had strict
500 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
501 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
502 ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
503 ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC),
504 Map.entry(RELEASE_4, // no bridge, varargs, synthetic
505 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
506 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
507 ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT),
508 Map.entry(RELEASE_1, // no strict
509 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
510 ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
511 ACC_NATIVE | ACC_ABSTRACT))),
512
513 /**
514 * Inner class location.
515 *
516 * @see Class#accessFlags()
517 * @see InnerClassInfo#flags()
518 * @jvms 4.7.6 The {@code InnerClasses} Attribute
519 */
520 INNER_CLASS(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
521 ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
522 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM,
523 List.of(Map.entry(RELEASE_4, // no synthetic, annotation, enum
524 ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
525 ACC_STATIC | ACC_FINAL | ACC_INTERFACE |
526 ACC_ABSTRACT),
527 Map.entry(RELEASE_0, 0))), // did not exist
528
529 /**
530 * Method parameter location.
531 *
532 * @see Parameter#accessFlags()
533 * @see MethodParameterInfo#flags()
534 * @jvms 4.7.24 The {@code MethodParameters} Attribute
535 */
536 METHOD_PARAMETER(ACC_FINAL | ACC_SYNTHETIC | ACC_MANDATED,
537 List.of(Map.entry(RELEASE_7, 0))), // did not exist
538
539 /**
540 * Module location.
541 *
542 * @see ModuleDescriptor#accessFlags()
543 * @see ModuleAttribute#moduleFlags()
544 * @jvms 4.7.25 The {@code Module} Attribute
545 */
546 MODULE(ACC_OPEN | ACC_SYNTHETIC | ACC_MANDATED,
547 List.of(Map.entry(RELEASE_8, 0))), // did not exist
548
549 /**
550 * Module requires location.
551 *
552 * @see ModuleDescriptor.Requires#accessFlags()
553 * @see ModuleRequireInfo#requiresFlags()
554 * @jvms 4.7.25 The {@code Module} Attribute
555 */
556 MODULE_REQUIRES(ACC_TRANSITIVE | ACC_STATIC_PHASE | ACC_SYNTHETIC | ACC_MANDATED,
557 List.of(Map.entry(RELEASE_8, 0))), // did not exist
558
559 /**
560 * Module exports location.
561 *
562 * @see ModuleDescriptor.Exports#accessFlags()
563 * @see ModuleExportInfo#exportsFlags()
564 * @jvms 4.7.25 The {@code Module} Attribute
565 */
566 MODULE_EXPORTS(ACC_SYNTHETIC | ACC_MANDATED,
567 List.of(Map.entry(RELEASE_8, 0))), // did not exist
568
569 /**
570 * Module opens location.
571 *
572 * @see ModuleDescriptor.Opens#accessFlags()
573 * @see ModuleOpenInfo#opensFlags()
574 * @jvms 4.7.25 The {@code Module} Attribute
575 */
576 MODULE_OPENS(ACC_SYNTHETIC | ACC_MANDATED,
577 List.of(Map.entry(RELEASE_8, 0))), // did not exist
578 ;
579
580 // Repeated sets of locations used by AccessFlag constants
581 private static final Set<Location> EMPTY_SET = Set.of();
582 private static final Set<Location> SET_MODULE = Set.of(MODULE);
583 private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS =
584 Set.of(CLASS, METHOD, INNER_CLASS);
585 private static final Set<Location> SET_CLASS_FIELD_METHOD =
586 Set.of(CLASS, FIELD, METHOD);
587 private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS =
588 Set.of(CLASS, FIELD, INNER_CLASS);
589 private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS =
590 Set.of(CLASS, FIELD, METHOD, INNER_CLASS);
591 private static final Set<Location> SET_CLASS_METHOD =
592 Set.of(CLASS, METHOD);
593 private static final Set<Location> SET_FIELD_METHOD =
594 Set.of(FIELD, METHOD);
595 private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS =
596 Set.of(FIELD, METHOD, INNER_CLASS);
597 private static final Set<Location> SET_METHOD = Set.of(METHOD);
598 private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER);
599 private static final Set<Location> SET_FIELD = Set.of(FIELD);
600 private static final Set<Location> SET_CLASS = Set.of(CLASS);
601 private static final Set<Location> SET_CLASS_INNER_CLASS =
602 Set.of(CLASS, INNER_CLASS);
603 private static final Set<Location> SET_MODULE_REQUIRES =
604 Set.of(MODULE_REQUIRES);
605 private static final Set<Location> SET_FINAL_8 =
606 Set.of(CLASS, FIELD, METHOD,
607 INNER_CLASS, /* added in 1.1 */
608 METHOD_PARAMETER); /* added in 8 */
609 private static final Set<Location> SET_SYNTHETIC_5 =
610 Set.of(CLASS, FIELD, METHOD,
611 INNER_CLASS);
612 private static final Set<Location> SET_SYNTHETIC_8 =
613 Set.of(CLASS, FIELD, METHOD,
614 INNER_CLASS, METHOD_PARAMETER);
615 private static final Set<Location> SET_SYNTHETIC_9 =
616 // Added as an access flag in 5.0
617 Set.of(CLASS, FIELD, METHOD,
618 INNER_CLASS,
619 METHOD_PARAMETER, // Added in 8
620 // Module-related items added in 9
621 MODULE, MODULE_REQUIRES,
622 MODULE_EXPORTS, MODULE_OPENS);
623 private static final Set<Location> SET_MANDATED_9 =
624 Set.of(METHOD_PARAMETER, // From 8
625 // Starting in 9
626 MODULE, MODULE_REQUIRES,
627 MODULE_EXPORTS, MODULE_OPENS);
628
629 private final int flagsMask;
630 private final List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks;
631
632 Location(int flagsMask,
633 List<Map.Entry<ClassFileFormatVersion, Integer>> historicalFlagsMasks) {
634 this.flagsMask = flagsMask;
635 this.historicalFlagsMasks = ensureHistoryOrdered(historicalFlagsMasks);
636 }
637
638 // Ensures the historical versions are from newest to oldest and do not include the latest
639 // These 2 utilities reside in Location because Location must be initialized before AccessFlag
640 private static <T> List<Map.Entry<ClassFileFormatVersion, T>> ensureHistoryOrdered(
641 List<Map.Entry<ClassFileFormatVersion, T>> history) {
642 ClassFileFormatVersion lastVersion = latest();
643 for (var e : history) {
644 var historyVersion = e.getKey();
645 if (lastVersion.compareTo(historyVersion) <= 0) {
646 throw new IllegalArgumentException("Versions out of order");
647 }
648 lastVersion = historyVersion;
649 }
650 return history;
651 }
652
653 private static <T> T findInHistory(T candidate, List<Map.Entry<ClassFileFormatVersion, T>> history,
654 ClassFileFormatVersion cffv) {
655 Objects.requireNonNull(cffv);
656 for (var e : history) {
657 if (e.getKey().compareTo(cffv) < 0) {
658 // last version found was valid
659 return candidate;
660 }
661 candidate = e.getValue();
662 }
663 return candidate;
664 }
665
666 /**
667 * {@return the union of masks of all access flags defined for
668 * this location in the current class file format version}
669 * <p>
670 * This method returns {@code 0} if this location does not exist in
671 * the current class file format version.
672 *
673 * @since 25
674 */
675 public int flagsMask() {
676 return flagsMask(latest());
677 }
678
679 /**
680 * {@return the union of masks of all access flags defined for
681 * this location in the given class file format version}
682 * <p>
683 * This method returns {@code 0} if this location does not exist in
684 * the given {@code cffv}.
685 *
686 * @param cffv the class file format version
687 * @throws NullPointerException if {@code cffv} is {@code null}
688 * @since 25
689 */
690 public int flagsMask(ClassFileFormatVersion cffv) {
691 return findInHistory(flagsMask, historicalFlagsMasks, cffv);
692 }
693
694 /**
695 * {@return the set of access flags defined for this location in the
696 * current class file format version} The set is immutable.
697 * <p>
698 * This method returns an empty set if this location does not exist
699 * in the current class file format version.
700 *
701 * @since 25
702 */
703 public Set<AccessFlag> flags() {
704 return flags(latest());
705 }
706
707 /**
708 * {@return the set of access flags defined for this location in the
709 * given class file format version} The set is immutable.
710 * <p>
711 * This method returns an empty set if this location does not exist
712 * in the given {@code cffv}.
713 *
714 * @param cffv the class file format version
715 * @throws NullPointerException if {@code cffv} is {@code null}
716 * @since 25
717 */
718 public Set<AccessFlag> flags(ClassFileFormatVersion cffv) {
719 // flagsMask null checks cffv and always returns valid mask
720 return AccessFlagSet.ofValidated(AccessFlagSet.findDefinition(this, cffv), flagsMask(cffv));
721 }
722 }
723 }