32
33 import java.util.*;
34 import java.nio.file.Path;
35 import java.nio.file.Paths;
36
37 import java.lang.classfile.*;
38 import java.lang.classfile.attribute.InnerClassInfo;
39 import java.lang.classfile.attribute.InnerClassesAttribute;
40
41 public class AnonymousClassFlags {
42 public static void main(String[] args) throws Exception {
43 new AnonymousClassFlags().test(System.getProperty("test.classes", "."));
44 }
45
46 /** Maps names of anonymous classes to their expected inner_class_access_flags */
47 private static Map<String, Integer> anonClasses = new LinkedHashMap<>();
48
49 // ******* TEST CASES ********
50
51 static Object o1 = new Object() {
52 { anonClasses.put(getClass().getName(), 0); }
53 };
54
55 static void staticMethod() {
56 Object o2 = new Object() {
57 { anonClasses.put(getClass().getName(), 0); }
58 };
59 }
60
61 static {
62 staticMethod();
63
64 Object o3 = new Object() {
65 { anonClasses.put(getClass().getName(), 0); }
66 };
67 }
68
69 Object o4 = new Object() {
70 { anonClasses.put(getClass().getName(), 0); }
71 };
72
73 void instanceMethod() {
74 Object o5 = new Object() {
75 { anonClasses.put(getClass().getName(), 0); }
76 };
77 }
78
79 {
80 instanceMethod();
81
82 Object o6 = new Object() {
83 { anonClasses.put(getClass().getName(), 0); }
84 };
85 }
86
87 // ******* TEST IMPLEMENTATION ********
88
89 void test(String classesDir) throws Exception {
90 staticMethod();
91 instanceMethod();
92
93 Path outerFile = Paths.get(classesDir, getClass().getName() + ".class");
94 ClassModel outerClass = ClassFile.of().parse(outerFile);
95 for (Map.Entry<String,Integer> entry : anonClasses.entrySet()) {
96 Path innerFile = Paths.get(classesDir, entry.getKey() + ".class");
97 ClassModel innerClass = ClassFile.of().parse(innerFile);
98 String name = entry.getKey();
99 int expected = entry.getValue();
100 assertInnerFlags(outerClass, name, expected);
101 assertClassFlags(innerClass, name, expected);
102 assertInnerFlags(innerClass, name, expected);
103 }
104 }
105
106 static void assertClassFlags(ClassModel classFile, String name, int expected) {
107 int mask = ClassFile.ACC_PUBLIC | ClassFile.ACC_FINAL | ClassFile.ACC_INTERFACE | ClassFile.ACC_ABSTRACT |
108 ClassFile.ACC_SYNTHETIC | ClassFile.ACC_ANNOTATION | ClassFile.ACC_ENUM;
109 int classExpected = (expected & mask) | ClassFile.ACC_SUPER;
110 int classActual = classFile.flags().flagsMask();
111 if (classActual != classExpected) {
112 throw new AssertionError("Incorrect access_flags for class " + name +
113 ": expected=" + classExpected + ", actual=" + classActual);
114 }
115
116 }
117
118 static void assertInnerFlags(ClassModel classFile, String name, int expected) {
119 int innerActual = lookupInnerFlags(classFile, name);
120 if (innerActual != expected) {
121 throw new AssertionError("Incorrect inner_class_access_flags for class " + name +
122 " in class " + classFile.thisClass().asInternalName() +
123 ": expected=" + expected + ", actual=" + innerActual);
124 }
125 }
126
127 private static int lookupInnerFlags(ClassModel classFile, String innerName) {
128 InnerClassesAttribute inners = classFile.findAttribute(Attributes.innerClasses()).orElse(null);
129 if (inners == null) {
|
32
33 import java.util.*;
34 import java.nio.file.Path;
35 import java.nio.file.Paths;
36
37 import java.lang.classfile.*;
38 import java.lang.classfile.attribute.InnerClassInfo;
39 import java.lang.classfile.attribute.InnerClassesAttribute;
40
41 public class AnonymousClassFlags {
42 public static void main(String[] args) throws Exception {
43 new AnonymousClassFlags().test(System.getProperty("test.classes", "."));
44 }
45
46 /** Maps names of anonymous classes to their expected inner_class_access_flags */
47 private static Map<String, Integer> anonClasses = new LinkedHashMap<>();
48
49 // ******* TEST CASES ********
50
51 static Object o1 = new Object() {
52 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
53 };
54
55 static void staticMethod() {
56 Object o2 = new Object() {
57 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
58 };
59 }
60
61 static {
62 staticMethod();
63
64 Object o3 = new Object() {
65 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
66 };
67 }
68
69 Object o4 = new Object() {
70 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
71 };
72
73 void instanceMethod() {
74 Object o5 = new Object() {
75 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
76 };
77 }
78
79 {
80 instanceMethod();
81
82 Object o6 = new Object() {
83 { anonClasses.put(getClass().getName(), ClassFile.ACC_IDENTITY); }
84 };
85 }
86
87 // ******* TEST IMPLEMENTATION ********
88
89 void test(String classesDir) throws Exception {
90 staticMethod();
91 instanceMethod();
92
93 Path outerFile = Paths.get(classesDir, getClass().getName() + ".class");
94 ClassModel outerClass = ClassFile.of().parse(outerFile);
95 for (Map.Entry<String,Integer> entry : anonClasses.entrySet()) {
96 Path innerFile = Paths.get(classesDir, entry.getKey() + ".class");
97 ClassModel innerClass = ClassFile.of().parse(innerFile);
98 String name = entry.getKey();
99 int expected = entry.getValue();
100 assertInnerFlags(outerClass, name, expected);
101 assertClassFlags(innerClass, name, expected);
102 assertInnerFlags(innerClass, name, expected);
103 }
104 }
105
106 static void assertClassFlags(ClassModel classFile, String name, int expected) {
107 int mask = ClassFile.ACC_PUBLIC | ClassFile.ACC_FINAL | ClassFile.ACC_INTERFACE | ClassFile.ACC_ABSTRACT |
108 ClassFile.ACC_SYNTHETIC | ClassFile.ACC_ANNOTATION | ClassFile.ACC_ENUM | ClassFile.ACC_IDENTITY;
109 int classExpected = (expected & mask);
110 int classActual = classFile.flags().flagsMask();
111 if (classActual != classExpected) {
112 throw new AssertionError("Incorrect access_flags for class " + name +
113 ": expected=" + classExpected + ", actual=" + classActual);
114 }
115
116 }
117
118 static void assertInnerFlags(ClassModel classFile, String name, int expected) {
119 int innerActual = lookupInnerFlags(classFile, name);
120 if (innerActual != expected) {
121 throw new AssertionError("Incorrect inner_class_access_flags for class " + name +
122 " in class " + classFile.thisClass().asInternalName() +
123 ": expected=" + expected + ", actual=" + innerActual);
124 }
125 }
126
127 private static int lookupInnerFlags(ClassModel classFile, String innerName) {
128 InnerClassesAttribute inners = classFile.findAttribute(Attributes.innerClasses()).orElse(null);
129 if (inners == null) {
|