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_INIT}, with a mask 373 * value of {@code 0x0800}. 374 * 375 * @jvms 4.5 Fields 376 * @since Valhalla 377 */ 378 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true) 379 STRICT_INIT(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 390 /** 391 * The access flag {@code ACC_SYNTHETIC} with a mask value of 392 * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>. 393 * @see Class#isSynthetic() 394 * @see Executable#isSynthetic() 395 * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC 396 */ 397 SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9, 398 new Function<ClassFileFormatVersion, Set<Location>>() { 399 @Override 400 public Set<Location> apply(ClassFileFormatVersion cffv) { 401 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) 402 return Location.SET_SYNTHETIC_9; 403 else { 404 return 405 switch(cffv) { 406 case RELEASE_7 -> Location.SET_SYNTHETIC_7; 407 case RELEASE_8 -> Location.SET_SYNTHETIC_8; 408 default -> Location.EMPTY_SET; 409 }; 410 } 411 } 412 }), 413 414 /** 415 * The access flag {@code ACC_ANNOTATION} with a mask value of 416 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>. 417 * @see Class#isAnnotation() 418 */ 419 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS, 420 new Function<ClassFileFormatVersion, Set<Location>>() { 421 @Override 422 public Set<Location> apply(ClassFileFormatVersion cffv) { 423 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 424 Location.SET_CLASS_INNER_CLASS: 425 Location.EMPTY_SET;} 426 }), 427 428 /** 429 * The access flag {@code ACC_ENUM} with a mask value of 430 * <code>{@value "0x%04x" Modifier#ENUM}</code>. 431 * @see Class#isEnum() 432 */ 433 ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS, 434 new Function<ClassFileFormatVersion, Set<Location>>() { 435 @Override 436 public Set<Location> apply(ClassFileFormatVersion cffv) { 437 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 438 Location.SET_CLASS_FIELD_INNER_CLASS: 439 Location.EMPTY_SET;} 440 }), 441 442 /** 443 * The access flag {@code ACC_MANDATED} with a mask value of 444 * <code>{@value "0x%04x" Modifier#MANDATED}</code>. 445 */ 446 MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9, 447 new Function<ClassFileFormatVersion, Set<Location>>() { 448 @Override 449 public Set<Location> apply(ClassFileFormatVersion cffv) { 450 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) { 451 return Location.SET_MANDATED_9; 452 } else { 453 return (cffv == ClassFileFormatVersion.RELEASE_8) ? 454 Location.SET_METHOD_PARAM: 455 Location.EMPTY_SET; 456 } 457 } 458 }), 459 460 /** 461 * The access flag {@code ACC_MODULE} with a mask value of {@code 462 * 0x8000}. 463 */ 464 MODULE(0x0000_8000, false, Location.SET_CLASS, 465 new Function<ClassFileFormatVersion, Set<Location>>() { 466 @Override 467 public Set<Location> apply(ClassFileFormatVersion cffv) { 468 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 469 Location.SET_CLASS: 470 Location.EMPTY_SET;} 471 }) 472 ; 473 474 // May want to override toString for a different enum constant -> 475 // name mapping. 476 477 private final int mask; 478 private final boolean sourceModifier; 479 480 // Intentionally using Set rather than EnumSet since EnumSet is 481 // mutable. 482 private final Set<Location> locations; 483 // Lambda to implement locations(ClassFileFormatVersion cffv) 484 private final Function<ClassFileFormatVersion, Set<Location>> cffvToLocations; 485 486 private AccessFlag(int mask, 487 boolean sourceModifier, 488 Set<Location> locations, 489 Function<ClassFileFormatVersion, Set<Location>> cffvToLocations) { 490 this.mask = mask; 491 this.sourceModifier = sourceModifier; 492 this.locations = locations; 493 this.cffvToLocations = cffvToLocations; 494 } 495 496 /** 497 * {@return the corresponding integer mask for the access flag} 498 */ 499 public int mask() { 500 return mask; 501 } 502 503 /** 504 * {@return whether or not the flag has a directly corresponding 505 * modifier in the Java programming language} 506 */ 507 public boolean sourceModifier() { 508 return sourceModifier; 509 } 510 511 /** 512 * {@return kinds of constructs the flag can be applied to in the 513 * latest class file format version} 514 */ 515 public Set<Location> locations() { 516 return locations; 517 } 518 519 /** 520 * {@return kinds of constructs the flag can be applied to in the 521 * given class file format version} 522 * @param cffv the class file format version to use 523 * @throws NullPointerException if the parameter is {@code null} 524 */ 525 public Set<Location> locations(ClassFileFormatVersion cffv) { 526 Objects.requireNonNull(cffv); 527 if (cffvToLocations == null) { 528 return locations; 529 } else { 530 return cffvToLocations.apply(cffv); 531 } 532 } 533 534 /** 535 * {@return an unmodifiable set of access flags for the given mask value 536 * appropriate for the location in question} 537 * 538 * @param mask bit mask of access flags 539 * @param location context to interpret mask value 540 * @throws IllegalArgumentException if the mask contains bit 541 * positions not supported for the location in question 542 */ 543 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) { 544 Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class); 545 for (var accessFlag : LocationToFlags.locationToFlags.get(location)) { 546 int accessMask = accessFlag.mask(); 547 if ((mask & accessMask) != 0) { 548 result.add(accessFlag); 549 mask = mask & ~accessMask; 550 if (mask == 0) { 551 break; // no more mask bits 552 } 553 } 554 } 555 if (mask != 0) { 556 throw new IllegalArgumentException("Unmatched bit position 0x" + 557 Integer.toHexString(mask) + 558 " for location " + location); 559 } 560 return Collections.unmodifiableSet(result); 561 } 562 563 /** 564 * {@return an unmodifiable set of access flags for the given mask value 565 * appropriate for the location in question} 566 * 567 * @param mask bit mask of access flags 568 * @param location context to interpret mask value 569 * @param cffv the class file format version 570 * @throws IllegalArgumentException if the mask contains bit 571 * positions not supported for the location in question 572 * 573 * @since Valhalla 574 */ 575 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location, 576 ClassFileFormatVersion cffv) { 577 Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class); 578 for (var accessFlag : AccessFlag.values()) { 579 int accessMask = accessFlag.mask(); 580 if ((mask & accessMask) != 0) { 581 var locations = accessFlag.locations(cffv); 582 if (locations.contains(location)) { 583 result.add(accessFlag); 584 mask = mask & ~accessMask; 585 if (mask == 0) { 586 break; // no more mask bits 587 } 588 } 589 } 590 } 591 if (mask != 0) { 592 throw new IllegalArgumentException("Unmatched bit position 0x" + 593 Integer.toHexString(mask) + 594 " for location " + location + 595 " for class file format version " + cffv); 596 } 597 return Collections.unmodifiableSet(result); 598 } 599 600 601 /** 602 * A location within a class file where flags can be applied. 603 * 604 * Note that since these locations represent class file structures 605 * rather than language structures many language structures, such 606 * as constructors and interfaces, are <em>not</em> present. 607 * @since 20 608 */ 609 public enum Location { 610 /** 611 * Class location. 612 * @jvms 4.1 The ClassFile Structure 613 */ 614 CLASS, 615 616 /** 617 * Field location. 618 * @jvms 4.5 Fields 619 */ 620 FIELD, 621 622 /** 623 * Method location. 624 * @jvms 4.6 Methods 625 */ 626 METHOD, 627 628 /** 629 * Inner class location. 630 * @jvms 4.7.6 The InnerClasses Attribute 631 */ 632 INNER_CLASS, 633 634 /** 635 * Method parameter location. 636 * @jvms 4.7.24 The MethodParameters Attribute 637 */ 638 METHOD_PARAMETER, 639 640 /** 641 * Module location 642 * @jvms 4.7.25 The Module Attribute 643 */ 644 MODULE, 645 646 /** 647 * Module requires location 648 * @jvms 4.7.25 The Module Attribute 649 */ 650 MODULE_REQUIRES, 651 652 /** 653 * Module exports location 654 * @jvms 4.7.25 The Module Attribute 655 */ 656 MODULE_EXPORTS, 657 658 /** 659 * Module opens location 660 * @jvms 4.7.25 The Module Attribute 661 */ 662 MODULE_OPENS; 663 664 // Repeated sets of locations used by AccessFlag constants 665 private static final Set<Location> EMPTY_SET = Set.of(); 666 private static final Set<Location> SET_MODULE = Set.of(MODULE); 667 private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS = 668 Set.of(CLASS, METHOD, INNER_CLASS); 669 private static final Set<Location> SET_CLASS_FIELD_METHOD = 670 Set.of(CLASS, FIELD, METHOD); 671 private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS = 672 Set.of(CLASS, FIELD, INNER_CLASS); 673 private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS = 674 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 675 private static final Set<Location> SET_CLASS_METHOD = 676 Set.of(CLASS, METHOD); 677 private static final Set<Location> SET_FIELD_METHOD = 678 Set.of(FIELD, METHOD); 679 private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS = 680 Set.of(FIELD, METHOD, INNER_CLASS); 681 private static final Set<Location> SET_METHOD = Set.of(METHOD); 682 private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER); 683 private static final Set<Location> SET_FIELD = Set.of(FIELD); 684 private static final Set<Location> SET_CLASS = Set.of(CLASS); 685 private static final Set<Location> SET_CLASS_INNER_CLASS = 686 Set.of(CLASS, INNER_CLASS); 687 private static final Set<Location> SET_MODULE_REQUIRES = 688 Set.of(MODULE_REQUIRES); 689 private static final Set<Location> SET_PUBLIC_1 = 690 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 691 private static final Set<Location> SET_FINAL_8 = 692 Set.of(CLASS, FIELD, METHOD, 693 INNER_CLASS, /* added in 1.1 */ 694 METHOD_PARAMETER); /* added in 8 */ 695 private static final Set<Location> SET_SYNTHETIC_7 = 696 Set.of(CLASS, FIELD, METHOD, 697 INNER_CLASS); 698 private static final Set<Location> SET_SYNTHETIC_8 = 699 Set.of(CLASS, FIELD, METHOD, 700 INNER_CLASS, METHOD_PARAMETER); 701 private static final Set<Location> SET_SYNTHETIC_9 = 702 // Added as an access flag in 7 703 Set.of(CLASS, FIELD, METHOD, 704 INNER_CLASS, 705 METHOD_PARAMETER, // Added in 8 706 // Module-related items added in 9 707 MODULE, MODULE_REQUIRES, 708 MODULE_EXPORTS, MODULE_OPENS); 709 private static final Set<Location> SET_MANDATED_9 = 710 Set.of(METHOD_PARAMETER, // From 8 711 // Starting in 9 712 MODULE, MODULE_REQUIRES, 713 MODULE_EXPORTS, MODULE_OPENS); 714 } 715 716 private static class LocationToFlags { 717 private static Map<Location, Set<AccessFlag>> locationToFlags = 718 Map.ofEntries(entry(Location.CLASS, 719 Set.of(PUBLIC, FINAL, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), 720 INTERFACE, ABSTRACT, 721 SYNTHETIC, ANNOTATION, 722 ENUM, AccessFlag.MODULE)), 723 entry(Location.FIELD, 724 PreviewFeatures.isEnabled() ? 725 // STRICT_INIT should be included only if preview is enabled 726 Set.of(PUBLIC, PRIVATE, PROTECTED, 727 STATIC, FINAL, VOLATILE, 728 TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT) : 729 Set.of(PUBLIC, PRIVATE, PROTECTED, 730 STATIC, FINAL, VOLATILE, 731 TRANSIENT, SYNTHETIC, ENUM)), 732 entry(Location.METHOD, 733 Set.of(PUBLIC, PRIVATE, PROTECTED, 734 STATIC, FINAL, SYNCHRONIZED, 735 BRIDGE, VARARGS, NATIVE, 736 ABSTRACT, STRICT, SYNTHETIC)), 737 entry(Location.INNER_CLASS, 738 Set.of(PUBLIC, PRIVATE, PROTECTED, (PreviewFeatures.isEnabled() ? IDENTITY : SUPER), 739 STATIC, FINAL, INTERFACE, ABSTRACT, 740 SYNTHETIC, ANNOTATION, ENUM)), 741 entry(Location.METHOD_PARAMETER, 742 Set.of(FINAL, SYNTHETIC, MANDATED)), 743 entry(Location.MODULE, 744 Set.of(OPEN, SYNTHETIC, MANDATED)), 745 entry(Location.MODULE_REQUIRES, 746 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)), 747 entry(Location.MODULE_EXPORTS, 748 Set.of(SYNTHETIC, MANDATED)), 749 entry(Location.MODULE_OPENS, 750 Set.of(SYNTHETIC, MANDATED))); 751 } 752 }