1 /* 2 * Copyright (c) 2021, 2024, 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.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 * 51 * <p>The values for the constants representing the access and module 52 * flags are taken from sections of <cite>The Java Virtual Machine 53 * Specification</cite> including {@jvms 4.1} (class access and 54 * property modifiers), {@jvms 4.5} (field access and property flags), 55 * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6} 56 * (nested class access and property flags), {@jvms 4.7.24} (method 57 * parameters), and {@jvms 4.7.25} (module flags and requires, 58 * exports, and opens flags). 59 * 60 * <p>The {@linkplain #mask() mask} values for the different access 61 * flags are <em>not</em> distinct. Flags are defined for different 62 * kinds of JVM structures and the same bit position has different 63 * meanings in different contexts. For example, {@code 0x0000_0040} 64 * indicates a {@link #VOLATILE volatile} field but a {@linkplain 65 * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link 66 * #TRANSIENT transient} field but a {@linkplain #VARARGS variable 67 * arity (varargs)} method. 68 * 69 * @implSpec 70 * The access flag constants are ordered by non-decreasing mask 71 * value; that is the mask value of a constant is greater than or 72 * equal to the mask value of an immediate neighbor to its (syntactic) 73 * left. If new constants are added, this property will be 74 * maintained. That implies new constants will not necessarily be 75 * added at the end of the existing list. 76 * 77 * @apiNote 78 * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new 79 * {@linkplain Runtime.Version#feature() feature release}. A new class 80 * file version may define new access flags or retire old ones. {@code 81 * AccessFlag} is intended to model the set of access flags across 82 * class file format versions. The range of versions an access flag is 83 * recognized is not explicitly indicated in this API. See the current 84 * <cite>The Java Virtual Machine Specification</cite> for 85 * details. Unless otherwise indicated, access flags can be assumed to 86 * be recognized in the {@linkplain Runtime#version() current 87 * version}. 88 * 89 * @see java.lang.reflect.Modifier 90 * @see java.lang.module.ModuleDescriptor.Modifier 91 * @see java.lang.module.ModuleDescriptor.Requires.Modifier 92 * @see java.lang.module.ModuleDescriptor.Exports.Modifier 93 * @see java.lang.module.ModuleDescriptor.Opens.Modifier 94 * @see java.compiler/javax.lang.model.element.Modifier 95 * @since 20 96 */ 97 @SuppressWarnings("doclint:reference") // cross-module link 98 public enum AccessFlag { 99 // Note to maintainers: anonymous class instances are used rather 100 // than lambdas to initialize the functions used for the 101 // cffvToLocations field to avoid using lambdas too early in JDK 102 // initialization. 103 104 /** 105 * The access flag {@code ACC_PUBLIC}, corresponding to the source 106 * modifier {@link Modifier#PUBLIC public}, with a mask value of 107 * <code>{@value "0x%04x" Modifier#PUBLIC}</code>. 108 */ 109 PUBLIC(Modifier.PUBLIC, true, 110 Location.SET_PUBLIC_1, 111 new Function<ClassFileFormatVersion, Set<Location>>() { 112 @Override 113 public Set<Location> apply(ClassFileFormatVersion cffv) { 114 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 115 Location.SET_CLASS_FIELD_METHOD: 116 Location.SET_PUBLIC_1; 117 } 118 }), 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 new Function<ClassFileFormatVersion, Set<Location>>() { 127 @Override 128 public Set<Location> apply(ClassFileFormatVersion cffv) { 129 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 130 Location.SET_FIELD_METHOD: 131 Location.SET_FIELD_METHOD_INNER_CLASS; 132 } 133 }), 134 135 /** 136 * The access flag {@code ACC_PROTECTED}, corresponding to the 137 * source modifier {@link Modifier#PROTECTED protected}, with a mask 138 * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>. 139 */ 140 PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS, 141 new Function<ClassFileFormatVersion, Set<Location>>() { 142 @Override 143 public Set<Location> apply(ClassFileFormatVersion cffv) { 144 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 145 Location.SET_FIELD_METHOD: 146 Location.SET_FIELD_METHOD_INNER_CLASS; 147 } 148 }), 149 150 /** 151 * The access flag {@code ACC_STATIC}, corresponding to the source 152 * modifier {@link Modifier#STATIC static}, with a mask value of 153 * <code>{@value "0x%04x" Modifier#STATIC}</code>. 154 */ 155 STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS, 156 new Function<ClassFileFormatVersion, Set<Location>>() { 157 @Override 158 public Set<Location> apply(ClassFileFormatVersion cffv) { 159 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 160 Location.SET_FIELD_METHOD: 161 Location.SET_FIELD_METHOD_INNER_CLASS;} 162 }), 163 164 /** 165 * The access flag {@code ACC_FINAL}, corresponding to the source 166 * modifier {@link Modifier#FINAL final}, with a mask 167 * value of <code>{@value "0x%04x" Modifier#FINAL}</code>. 168 */ 169 FINAL(Modifier.FINAL, true, 170 Location.SET_FINAL_8, 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 294 /** 295 * The access flag {@code ACC_TRANSIENT}, corresponding to the 296 * source modifier {@link Modifier#TRANSIENT transient}, with a 297 * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>. 298 */ 299 TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, null), 300 301 /** 302 * The access flag {@code ACC_VARARGS} with a mask value of 303 <code>{@value "0x%04x" Modifier#VARARGS}</code>. 304 * @see Executable#isVarArgs() 305 */ 306 VARARGS(Modifier.VARARGS, false, Location.SET_METHOD, 307 new Function<ClassFileFormatVersion, Set<Location>>() { 308 @Override 309 public Set<Location> apply(ClassFileFormatVersion cffv) { 310 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 311 Location.SET_METHOD: 312 Location.EMPTY_SET;} 313 }), 314 315 /** 316 * The access flag {@code ACC_NATIVE}, corresponding to the source 317 * modifier {@link Modifier#NATIVE native}, with a mask value of 318 * <code>{@value "0x%04x" Modifier#NATIVE}</code>. 319 */ 320 NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, null), 321 322 /** 323 * The access flag {@code ACC_INTERFACE} with a mask value of 324 * {@code 0x0200}. 325 * @see Class#isInterface() 326 */ 327 INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS, 328 new Function<ClassFileFormatVersion, Set<Location>>() { 329 @Override 330 public Set<Location> apply(ClassFileFormatVersion cffv) { 331 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ? 332 Location.SET_CLASS: 333 Location.SET_CLASS_INNER_CLASS;} 334 }), 335 336 /** 337 * The access flag {@code ACC_ABSTRACT}, corresponding to the 338 * source modifier {@link Modifier#ABSTRACT abstract}, with a mask 339 * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>. 340 */ 341 ABSTRACT(Modifier.ABSTRACT, true, 342 Location.SET_CLASS_METHOD_INNER_CLASS, 343 new Function<ClassFileFormatVersion, Set<Location>>() { 344 @Override 345 public Set<Location> apply(ClassFileFormatVersion cffv) { 346 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ? 347 Location.SET_CLASS_METHOD: 348 Location.SET_CLASS_METHOD_INNER_CLASS;} 349 }), 350 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 }; 415 } 416 } 417 }), 418 419 /** 420 * The access flag {@code ACC_ANNOTATION} with a mask value of 421 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>. 422 * @see Class#isAnnotation() 423 */ 424 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS, 425 new Function<ClassFileFormatVersion, Set<Location>>() { 426 @Override 427 public Set<Location> apply(ClassFileFormatVersion cffv) { 428 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 429 Location.SET_CLASS_INNER_CLASS: 430 Location.EMPTY_SET;} 431 }), 432 433 /** 434 * The access flag {@code ACC_ENUM} with a mask value of 435 * <code>{@value "0x%04x" Modifier#ENUM}</code>. 436 * @see Class#isEnum() 437 */ 438 ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS, 439 new Function<ClassFileFormatVersion, Set<Location>>() { 440 @Override 441 public Set<Location> apply(ClassFileFormatVersion cffv) { 442 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 443 Location.SET_CLASS_FIELD_INNER_CLASS: 444 Location.EMPTY_SET;} 445 }), 446 447 /** 448 * The access flag {@code ACC_MANDATED} with a mask value of 449 * <code>{@value "0x%04x" Modifier#MANDATED}</code>. 450 */ 451 MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9, 452 new Function<ClassFileFormatVersion, Set<Location>>() { 453 @Override 454 public Set<Location> apply(ClassFileFormatVersion cffv) { 455 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) { 456 return Location.SET_MANDATED_9; 457 } else { 458 return (cffv == ClassFileFormatVersion.RELEASE_8) ? 459 Location.SET_METHOD_PARAM: 460 Location.EMPTY_SET; 461 } 462 } 463 }), 464 465 /** 466 * The access flag {@code ACC_MODULE} with a mask value of {@code 467 * 0x8000}. 468 */ 469 MODULE(0x0000_8000, false, Location.SET_CLASS, 470 new Function<ClassFileFormatVersion, Set<Location>>() { 471 @Override 472 public Set<Location> apply(ClassFileFormatVersion cffv) { 473 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 474 Location.SET_CLASS: 475 Location.EMPTY_SET;} 476 }) 477 ; 478 479 // May want to override toString for a different enum constant -> 480 // name mapping. 481 482 private final int mask; 483 private final boolean sourceModifier; 484 485 // Intentionally using Set rather than EnumSet since EnumSet is 486 // mutable. 487 private final Set<Location> locations; 488 // Lambda to implement locations(ClassFileFormatVersion cffv) 489 private final Function<ClassFileFormatVersion, Set<Location>> cffvToLocations; 490 491 private AccessFlag(int mask, 492 boolean sourceModifier, 493 Set<Location> locations, 494 Function<ClassFileFormatVersion, Set<Location>> cffvToLocations) { 495 this.mask = mask; 496 this.sourceModifier = sourceModifier; 497 this.locations = locations; 498 this.cffvToLocations = cffvToLocations; 499 } 500 501 /** 502 * {@return the corresponding integer mask for the access flag} 503 */ 504 public int mask() { 505 return mask; 506 } 507 508 /** 509 * {@return whether or not the flag has a directly corresponding 510 * modifier in the Java programming language} 511 */ 512 public boolean sourceModifier() { 513 return sourceModifier; 514 } 515 516 /** 517 * {@return kinds of constructs the flag can be applied to in the 518 * latest class file format version} 519 */ 520 public Set<Location> locations() { 521 return locations; 522 } 523 524 /** 525 * {@return kinds of constructs the flag can be applied to in the 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, 624 625 /** 626 * Method location. 627 * @jvms 4.6 Methods 628 */ 629 METHOD, 630 631 /** 632 * Inner class location. 633 * @jvms 4.7.6 The InnerClasses Attribute 634 */ 635 INNER_CLASS, 636 637 /** 638 * Method parameter location. 639 * @jvms 4.7.24 The MethodParameters Attribute 640 */ 641 METHOD_PARAMETER, 642 643 /** 644 * Module location 645 * @jvms 4.7.25 The Module Attribute 646 */ 647 MODULE, 648 649 /** 650 * Module requires location 651 * @jvms 4.7.25 The Module Attribute 652 */ 653 MODULE_REQUIRES, 654 655 /** 656 * Module exports location 657 * @jvms 4.7.25 The Module Attribute 658 */ 659 MODULE_EXPORTS, 660 661 /** 662 * Module opens location 663 * @jvms 4.7.25 The Module Attribute 664 */ 665 MODULE_OPENS; 666 667 // Repeated sets of locations used by AccessFlag constants 668 private static final Set<Location> EMPTY_SET = Set.of(); 669 private static final Set<Location> SET_MODULE = Set.of(MODULE); 670 private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS = 671 Set.of(CLASS, METHOD, INNER_CLASS); 672 private static final Set<Location> SET_CLASS_FIELD_METHOD = 673 Set.of(CLASS, FIELD, METHOD); 674 private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS = 675 Set.of(CLASS, FIELD, INNER_CLASS); 676 private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS = 677 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 678 private static final Set<Location> SET_CLASS_METHOD = 679 Set.of(CLASS, METHOD); 680 private static final Set<Location> SET_FIELD_METHOD = 681 Set.of(FIELD, METHOD); 682 private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS = 683 Set.of(FIELD, METHOD, INNER_CLASS); 684 private static final Set<Location> SET_METHOD = Set.of(METHOD); 685 private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER); 686 private static final Set<Location> SET_FIELD = Set.of(FIELD); 687 private static final Set<Location> SET_CLASS = Set.of(CLASS); 688 private static final Set<Location> SET_CLASS_INNER_CLASS = 689 Set.of(CLASS, INNER_CLASS); 690 private static final Set<Location> SET_MODULE_REQUIRES = 691 Set.of(MODULE_REQUIRES); 692 private static final Set<Location> SET_PUBLIC_1 = 693 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 694 private static final Set<Location> SET_FINAL_8 = 695 Set.of(CLASS, FIELD, METHOD, 696 INNER_CLASS, /* added in 1.1 */ 697 METHOD_PARAMETER); /* added in 8 */ 698 private static final Set<Location> SET_SYNTHETIC_7 = 699 Set.of(CLASS, FIELD, METHOD, 700 INNER_CLASS); 701 private static final Set<Location> SET_SYNTHETIC_8 = 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 }