{@value "0x%04x" Modifier#PUBLIC}
.
*/
PUBLIC(Modifier.PUBLIC, true,
- Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
- Location.INNER_CLASS)),
+ Location.SET_PUBLIC_1,
+ cffv -> {
+ return (cffv == ClassFileFormatVersion.RELEASE_0) ?
+ Location.SET_CLASS_FIELD_METHOD:
+ Location.SET_PUBLIC_1;
+ }),
/**
* The access flag {@code ACC_PRIVATE}, corresponding to the
* source modifier {@link Modifier#PRIVATE private} with a mask
* value of {@value "0x%04x" Modifier#PRIVATE}
.
*/
- PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS),
+ PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS,
+ cffv -> {
+ return (cffv == ClassFileFormatVersion.RELEASE_0) ?
+ Location.SET_FIELD_METHOD:
+ Location.SET_FIELD_METHOD_INNER_CLASS;
+ }),
/**
* The access flag {@code ACC_PROTECTED}, corresponding to the
* source modifier {@link Modifier#PROTECTED protected} with a mask
* value of {@value "0x%04x" Modifier#PROTECTED}
.
*/
- PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS),
+ PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS,
+ cffv -> {return (cffv == ClassFileFormatVersion.RELEASE_0) ?
+ Location.SET_FIELD_METHOD:
+ Location.SET_FIELD_METHOD_INNER_CLASS;}),
/**
* The access flag {@code ACC_STATIC}, corresponding to the source
* modifier {@link Modifier#STATIC static} with a mask value of
* {@value "0x%04x" Modifier#STATIC}
.
*/
- STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS),
+ STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS,
+ cffv -> {return (cffv == ClassFileFormatVersion.RELEASE_0) ?
+ Location.SET_FIELD_METHOD:
+ Location.SET_FIELD_METHOD_INNER_CLASS;}),
/**
* The access flag {@code ACC_FINAL}, corresponding to the source
@@ -127,8 +143,16 @@ public enum AccessFlag {
* value of {@value "0x%04x" Modifier#FINAL}
.
*/
FINAL(Modifier.FINAL, true,
- Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
- Location.INNER_CLASS, Location.METHOD_PARAMETER)),
+ Location.SET_FINAL_8,
+ cffv -> {
+ if (cffv.compareTo(ClassFileFormatVersion.RELEASE_8) >= 0) {
+ return Location.SET_FINAL_8;
+ } else {
+ return (cffv == ClassFileFormatVersion.RELEASE_0) ?
+ Location.SET_CLASS_FIELD_METHOD :
+ Location.SET_CLASS_FIELD_METHOD_INNER_CLASS;
+ }
+ }),
/**
* The access flag {@code ACC_SUPER} with a mask value of {@code
@@ -138,77 +162,96 @@ public enum AccessFlag {
* In Java SE 8 and above, the JVM treats the {@code ACC_SUPER}
* flag as set in every class file (JVMS {@jvms 4.1}).
*/
- SUPER(0x0000_0020, false, Location.SET_CLASS),
+ SUPER(0x0000_0020, false, Location.SET_CLASS, null),
/**
* The module flag {@code ACC_OPEN} with a mask value of {@code
* 0x0020}.
* @see java.lang.module.ModuleDescriptor#isOpen
*/
- OPEN(0x0000_0020, false, Set.of(Location.MODULE)),
+ OPEN(0x0000_0020, false, Location.SET_MODULE,
+ cffv -> { return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
+ Location.SET_MODULE:
+ Location.EMPTY_SET;}),
/**
* The module requires flag {@code ACC_TRANSITIVE} with a mask
* value of {@code 0x0020}.
* @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
*/
- TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES),
+ TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
+ Location.SET_MODULE_REQUIRES:
+ Location.EMPTY_SET;}),
/**
* The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
* source modifier {@link Modifier#SYNCHRONIZED synchronized} with
* a mask value of {@value "0x%04x" Modifier#SYNCHRONIZED}
.
*/
- SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD),
+ SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, null),
/**
* The module requires flag {@code ACC_STATIC_PHASE} with a mask
* value of {@code 0x0040}.
* @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
*/
- STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES),
+ STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
+ Location.SET_MODULE_REQUIRES:
+ Location.EMPTY_SET;}),
- /**
- * The access flag {@code ACC_VOLATILE}, corresponding to the
- * source modifier {@link Modifier#VOLATILE volatile} with a mask
- * value of {@value "0x%04x" Modifier#VOLATILE}
.
- */
- VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD),
+ /**
+ * The access flag {@code ACC_VOLATILE}, corresponding to the
+ * source modifier {@link Modifier#VOLATILE volatile} with a mask
+ * value of {@value "0x%04x" Modifier#VOLATILE}
.
+ */
+ VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, null),
/**
* The access flag {@code ACC_BRIDGE} with a mask value of
* {@value "0x%04x" Modifier#BRIDGE}
* @see Method#isBridge()
*/
- BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD),
+ BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
+ Location.SET_METHOD:
+ Location.EMPTY_SET;}),
/**
* The access flag {@code ACC_TRANSIENT}, corresponding to the
* source modifier {@link Modifier#TRANSIENT transient} with a
* mask value of {@value "0x%04x" Modifier#TRANSIENT}
.
*/
- TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD),
+ TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, null),
/**
* The access flag {@code ACC_VARARGS} with a mask value of
{@value "0x%04x" Modifier#VARARGS}
.
* @see Executable#isVarArgs()
*/
- VARARGS(Modifier.VARARGS, false, Location.SET_METHOD),
+ VARARGS(Modifier.VARARGS, false, Location.SET_METHOD,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
+ Location.SET_METHOD:
+ Location.EMPTY_SET;}),
+
/**
* The access flag {@code ACC_NATIVE}, corresponding to the source
* modifier {@link Modifier#NATIVE native} with a mask value of
* {@value "0x%04x" Modifier#NATIVE}
.
*/
- NATIVE(Modifier.NATIVE, true, Location.SET_METHOD),
+ NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, null),
/**
* The access flag {@code ACC_INTERFACE} with a mask value of
* {@code 0x0200}.
* @see Class#isInterface()
*/
- INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS),
+ INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS,
+ cffv -> { return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ?
+ Location.SET_CLASS:
+ Location.SET_CLASS_INNER_CLASS;}),
/**
* The access flag {@code ACC_ABSTRACT}, corresponding to the
@@ -216,7 +259,10 @@ public enum AccessFlag {
* value of {@value "0x%04x" Modifier#ABSTRACT}
.
*/
ABSTRACT(Modifier.ABSTRACT, true,
- Set.of(Location.CLASS, Location.METHOD, Location.INNER_CLASS)),
+ Location.SET_CLASS_METHOD_INNER_CLASS,
+ cffv -> { return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ?
+ Location.SET_CLASS_METHOD:
+ Location.SET_CLASS_METHOD_INNER_CLASS;}),
/**
* The access flag {@code ACC_STRICT}, corresponding to the source
@@ -228,7 +274,12 @@ public enum AccessFlag {
* major versions 46 through 60, inclusive (JVMS {@jvms 4.6}),
* corresponding to Java SE 1.2 through 16.
*/
- STRICT(Modifier.STRICT, true, Location.SET_METHOD),
+ STRICT(Modifier.STRICT, true, Location.SET_METHOD,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_2) >= 0 &&
+ cffv.compareTo(ClassFileFormatVersion.RELEASE_16) <= 0) ?
+ Location.SET_METHOD:
+ Location.EMPTY_SET;}),
+
/**
* The access flag {@code ACC_SYNTHETIC} with a mask value of
@@ -237,41 +288,63 @@ public enum AccessFlag {
* @see Executable#isSynthetic()
* @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
*/
- SYNTHETIC(Modifier.SYNTHETIC, false,
- Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
- Location.INNER_CLASS, Location.METHOD_PARAMETER,
- Location.MODULE, Location.MODULE_REQUIRES,
- Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
+ SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9,
+ cffv -> {
+ if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 )
+ return Location.SET_SYNTHETIC_9;
+ else {
+ return
+ switch(cffv) {
+ case RELEASE_7 -> Location.SET_SYNTHETIC_7;
+ case RELEASE_8 -> Location.SET_SYNTHETIC_8;
+ default -> Location.EMPTY_SET;
+ };
+ }
+ }),
/**
* The access flag {@code ACC_ANNOTATION} with a mask value of
* {@value "0x%04x" Modifier#ANNOTATION}
.
* @see Class#isAnnotation()
*/
- ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS),
+ ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
+ Location.SET_CLASS_INNER_CLASS:
+ Location.EMPTY_SET;}),
/**
* The access flag {@code ACC_ENUM} with a mask value of
* {@value "0x%04x" Modifier#ENUM}
.
* @see Class#isEnum()
*/
- ENUM(Modifier.ENUM, false,
- Set.of(Location.CLASS, Location.FIELD, Location.INNER_CLASS)),
+ ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ?
+ Location.SET_CLASS_FIELD_INNER_CLASS:
+ Location.EMPTY_SET;}),
/**
* The access flag {@code ACC_MANDATED} with a mask value of
* {@value "0x%04x" Modifier#MANDATED}
.
*/
- MANDATED(Modifier.MANDATED, false,
- Set.of(Location.METHOD_PARAMETER,
- Location.MODULE, Location.MODULE_REQUIRES,
- Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
+ MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9,
+ cffv -> {
+ if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) {
+ return Location.SET_MANDATED_9;
+ } else {
+ return (cffv == ClassFileFormatVersion.RELEASE_8) ?
+ Location.SET_METHOD_PARAM:
+ Location.EMPTY_SET;
+ }
+ }),
/**
* The access flag {@code ACC_MODULE} with a mask value of {@code
* 0x8000}.
*/
- MODULE(0x0000_8000, false, Location.SET_CLASS)
+ MODULE(0x0000_8000, false, Location.SET_CLASS,
+ cffv -> {return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ?
+ Location.SET_CLASS:
+ Location.EMPTY_SET;})
;
// May want to override toString for a different enum constant ->
@@ -283,11 +356,17 @@ public enum AccessFlag {
// Intentionally using Set rather than EnumSet since EnumSet is
// mutable.
private final SetNote that additional class file format version constants will be + * added to model future releases of the Java Virtual Machine + * Specification. + * + * @since 20 + * @see System#getProperties System property {@code java.class.version} + * @see java.compiler/javax.lang.model.SourceVersion + */ +@SuppressWarnings("doclint:reference") // cross-module links +public enum ClassFileFormatVersion { + + /** + * The original version. + * + * The format described in The Java Virtual Specification, + * First Edition. + */ + RELEASE_0(45), + + /** + * The version recognized by the Java Platform 1.1. + * + * @apiNote + * While {@code RELEASE_0} and {@code RELEASE_1} have the same + * {@linkplain #major() major version}, several additional + * attributes were defined for {@code RELEASE_1} (JVMS {@jvms + * 4.7}). + * + */ + RELEASE_1(45), + + /** + * The version recognized by the Java 2 Platform, Standard Edition, + * v 1.2. + * + * The format described in The Java Virtual Machine + * Specification, Second Edition, which includes the {@link + * AccessFlag#STRICT ACC_STRICT} access flag. + */ + RELEASE_2(46), + + /** + * The version recognized by the Java 2 Platform, Standard Edition, + * v 1.3. + */ + RELEASE_3(47), + + /** + * The version recognized by the Java 2 Platform, Standard Edition, + * v 1.4. + */ + RELEASE_4(48), + + /** + * The version recognized by the Java 2 Platform, Standard + * Edition 5.0. + * + * @see + * The Java Virtual Machine Specification, Second Edition updated for Java SE 5.0 + * @see + * JSR 14: Add Generic Types To The Java™ Programming Language + * @see + * JSR 175: A Metadata Facility for the Java™ Programming Language + */ + RELEASE_5(49), + + /** + * The version recognized by the Java Platform, Standard Edition + * 6. + * + * @see + * The Java Virtual Machine Specification, Java SE, Second Edition updated for Java SE 6 + */ + RELEASE_6(50), + + /** + * The version recognized by the Java Platform, Standard Edition + * 7. + * + * @see + * The Java Virtual Machine Specification, Java SE 7 Edition + */ + RELEASE_7(51), + + /** + * The version recognized by the Java Platform, Standard Edition + * 8. + * + * @see + * The Java Virtual Machine Specification, Java SE 8 Edition + * @see + * JSR 335: Lambda Expressions for the Java™ Programming Language + */ + RELEASE_8(52), + + /** + * The version recognized by the Java Platform, Standard Edition + * 9. + * + * @see + * The Java Virtual Machine Specification, Java SE 9 Edition + * @see + * JSR 376: Java™ Platform Module System + */ + RELEASE_9(53), + + /** + * The version recognized by the Java Platform, Standard Edition + * 10. + * + * @see + * The Java Virtual Machine Specification, Java SE 10 Edition + */ + RELEASE_10(54), + + /** + * The version recognized by the Java Platform, Standard Edition + * 11. + * + * @see + * The Java Virtual Machine Specification, Java SE 11 Edition + * @see + * JEP 181: Nest-Based Access Control + */ + RELEASE_11(55), + + /** + * The version recognized by the Java Platform, Standard Edition + * 12. + * + * @see + * The Java Virtual Machine Specification, Java SE 12 Edition + */ + RELEASE_12(56), + + /** + * The version recognized by the Java Platform, Standard Edition + * 13. + * + * @see + * The Java Virtual Machine Specification, Java SE 13 Edition + */ + RELEASE_13(57), + + /** + * The version recognized by the Java Platform, Standard Edition + * 14. + * + * @see + * The Java Virtual Machine Specification, Java SE 14 Edition + */ + RELEASE_14(58), + + /** + * The version recognized by the Java Platform, Standard Edition + * 15. + * + * @see + * The Java Virtual Machine Specification, Java SE 15 Edition + * @see + * JEP 371: Hidden Classes + */ + RELEASE_15(59), + + /** + * The version recognized by the Java Platform, Standard Edition + * 16. + * + * @see + * The Java Virtual Machine Specification, Java SE 16 Edition + */ + RELEASE_16(60), + + /** + * The version recognized by the Java Platform, Standard Edition + * 17. + * + * Additions in this release include sealed classes and + * restoration of always-strict floating-point semantics. + * + * @see + * The Java Virtual Machine Specification, Java SE 17 Edition + * @see + * JEP 306: Restore Always-Strict Floating-Point Semantics + * @see + * JEP 409: Sealed Classes + */ + RELEASE_17(61), + + /** + * The version recognized by the Java Platform, Standard Edition + * 18. + * + * @see + * The Java Virtual Machine Specification, Java SE 18 Edition + */ + RELEASE_18(62), + + /** + * The version recognized by the Java Platform, Standard Edition + * 19. + */ + RELEASE_19(63), + + /** + * The version recognized by the Java Platform, Standard Edition + * 20. + */ + RELEASE_20(64); + + // Note to maintainers: when adding constants for newer releases, + // the implementation of latest() must be updated too. + + private final int major; + + private ClassFileFormatVersion(int major) { + this.major = major; + } + + /** + * {@return the latest class file format version} + */ + public static ClassFileFormatVersion latest() { + return RELEASE_20; + } + + /** + * {@return the major class file version as an integer} + * @jvms 4.1 The {@code ClassFile} Structure + */ + public int major() { + return major; + } + + /** + * {@return the latest class file format version that is usable + * under the runtime version argument} If the runtime version's + * {@linkplain Runtime.Version#feature() feature} is greater than + * the feature of the {@linkplain #runtimeVersion() runtime + * version} of the {@linkplain #latest() latest class file format + * version}, an {@code IllegalArgumentException} is thrown. + * + *
Because the class file format versions of the Java platform
+ * have so far followed a linear progression, only the feature
+ * component of a runtime version is queried to determine the
+ * mapping to a class file format version. If that linearity
+ * changes in the future, other components of the runtime version
+ * may influence the result.
+ *
+ * @apiNote
+ * An expression to convert from a string value, for example
+ * {@code "17"}, to the corresponding class file format version,
+ * {@code RELEASE_17}, is:
+ *
+ * {@snippet lang="java" :
+ * ClassFileFormatVersion.valueOf(Runtime.Version.parse("17"))}
+ *
+ * @param rv runtime version to map to a class file format version
+ * @throws IllegalArgumentException if the feature of version
+ * argument is greater than the feature of the platform version.
+ */
+ public static ClassFileFormatVersion valueOf(Runtime.Version rv) {
+ // Could also implement this as a switch where a case was
+ // added with each new release.
+ return valueOf("RELEASE_" + rv.feature());
+ }
+
+ /**
+ * {@return the least runtime version that supports this class
+ * file format version; otherwise {@code null}} The returned
+ * runtime version has a {@linkplain Runtime.Version#feature()
+ * feature} large enough to support this class file format version
+ * and has no other elements set.
+ *
+ * Class file format versions greater than or equal to {@link
+ * RELEASE_6} have non-{@code null} results.
+ */
+ public Runtime.Version runtimeVersion() {
+ // Starting with Java SE 6, the leading digit was the primary
+ // way of identifying the platform version.
+ if (this.compareTo(RELEASE_6) >= 0) {
+ return Runtime.Version.parse(Integer.toString(ordinal()));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * {@return the latest class file format version whose major class
+ * file version matches the argument}
+ * @param major the major class file version as an integer
+ * @throws IllegalArgumentException if the argument is outside of
+ * the range of major class file versions
+ */
+ public static ClassFileFormatVersion fromMajor(int major) {
+ if (major < 45 // RELEASE_0.major()
+ || major > latest().major()) {
+ throw new IllegalArgumentException("Out of range major class file vesion "
+ + major);
+ }
+ // RELEASE_0 and RELEASE_1 both have a major version of 45;
+ // return RELEASE_1 for an argument of 45.
+ return values()[major-44];
+ }
+}
diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
index c0c56b9bb67..caf6ae754f3 100644
--- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
+++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
@@ -40,6 +40,7 @@ import java.util.HashSet;
* model future releases of the language.
*
* @since 1.6
+ * @see java.lang.reflect.ClassFileFormatVersion
*/
public enum SourceVersion {
/*
diff --git a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java
index 6dc6a47bbcf..01921182353 100644
--- a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java
+++ b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java
@@ -66,8 +66,7 @@ public class ClassFileVersionTest {
m = cl.getDeclaredMethod("getClassFileVersion", new Class[0]);
m.setAccessible(true);
- // Class file version is stored like "64.0".
- int latestMajor = (int)Double.parseDouble(System.getProperty("java.class.version"));
+ int latestMajor = ClassFileFormatVersion.latest().major();
testIt(Object.class, latestMajor);
// ClassFileVersionTest use preview features so its minor version should be 0xFFFF
diff --git a/test/jdk/java/lang/reflect/AccessFlag/FieldAccessFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/FieldAccessFlagTest.java
index ab8109d186b..edd35f7b6a3 100644
--- a/test/jdk/java/lang/reflect/AccessFlag/FieldAccessFlagTest.java
+++ b/test/jdk/java/lang/reflect/AccessFlag/FieldAccessFlagTest.java
@@ -34,7 +34,7 @@ import java.lang.reflect.*;
* Field modifiers include:
* public, private, protected, static, final, volatile, transient,
*
- * Additionall, the access flags enum and synthetic cannot be
+ * Additionally, the access flags enum and synthetic cannot be
* explicitly applied.
*/
public class FieldAccessFlagTest {
diff --git a/test/jdk/java/lang/reflect/AccessFlag/VersionedLocationsTest.java b/test/jdk/java/lang/reflect/AccessFlag/VersionedLocationsTest.java
new file mode 100644
index 00000000000..b79ad5ab1a7
--- /dev/null
+++ b/test/jdk/java/lang/reflect/AccessFlag/VersionedLocationsTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8289106
+ * @summary Tests of AccessFlag.locations(ClassFileFormatVersion)
+ */
+
+import java.lang.reflect.AccessFlag;
+import static java.lang.reflect.AccessFlag.*;
+import java.lang.reflect.ClassFileFormatVersion;
+import java.util.HashSet;
+import java.util.Set;
+
+/*
+ * There are several patterns of access flag applicability. First, an
+ * access flag can be applied to the same set of locations for each
+ * class file format version. This is "invariant" usage. Second, an
+ * access flag can be defined for version N, therefore inapplicable
+ * for earlier versions, and then applied to the same locations for
+ * all subsequent versions. This is "step" usage. Finally, an access
+ * flag to have a more complicated pattern, having multiple steps of
+ * being allowed at more locations or even having locations removed if
+ * the access flag is retired.
+ *
+ * List of access flags and how they are tested:
+ *
+ * PUBLIC step
+ * PRIVATE step
+ * PROTECTED step
+ * STATIC step
+ * FINAL two-step
+ * SUPER invariant
+ * OPEN step
+ * TRANSITIVE step
+ * SYNCHRONIZED invariant
+ * STATIC_PHASE step
+ * VOLATILE invariant
+ * BRIDGE step
+ * TRANSIENT invariant
+ * VARARGS step
+ * NATIVE invariant
+ * INTERFACE step
+ * ABSTRACT step
+ * STRICT other
+ * SYNTHETIC other (three-step)
+ * ANNOTATION step
+ * ENUM step
+ * MANDATED two-step
+ * MODULE step
+ */
+
+public class VersionedLocationsTest {
+ public static void main(String... args) throws Exception {
+ testInvariantAccessFlags();
+ testStepFunctionAccessFlags();
+ testTwoStepAccessFlags();
+ testSynthetic();
+ testStrict();
+ }
+
+ /**
+ * Invariant access flags have the same set of locations for each
+ * class file format version.
+ */
+ private static void testInvariantAccessFlags() {
+ Set