24 /*
25 * @test
26 * @modules java.base/jdk.internal.org.objectweb.asm
27 * jdk.compiler
28 * @library /test/lib
29 * @compile BadClassFile.jcod
30 * BadClassFile2.jcod
31 * BadClassFileVersion.jcod
32 * @build jdk.test.lib.Utils
33 * jdk.test.lib.compiler.CompilerUtils
34 * @run testng/othervm BasicTest
35 */
36
37 import java.io.File;
38 import java.io.IOException;
39 import java.lang.invoke.MethodHandles.Lookup;
40
41 import static java.lang.invoke.MethodHandles.lookup;
42 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
43
44 import java.lang.reflect.Array;
45 import java.lang.reflect.Method;
46 import java.nio.charset.StandardCharsets;
47 import java.nio.file.Files;
48 import java.nio.file.Path;
49 import java.nio.file.Paths;
50 import java.util.Arrays;
51 import java.util.List;
52 import java.util.stream.Stream;
53
54 import jdk.internal.org.objectweb.asm.ClassWriter;
55 import jdk.internal.org.objectweb.asm.Type;
56 import jdk.test.lib.compiler.CompilerUtils;
57 import jdk.test.lib.Utils;
58
59 import org.testng.annotations.BeforeTest;
60 import org.testng.annotations.DataProvider;
61 import org.testng.annotations.Test;
62
63 import static jdk.internal.org.objectweb.asm.Opcodes.*;
97
98 static Class<?> defineHiddenClass(String name) throws Exception {
99 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
100 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
101 assertHiddenClass(hc);
102 singletonNest(hc);
103 return hc;
104 }
105
106 // basic test on a hidden class
107 @Test
108 public void hiddenClass() throws Throwable {
109 HiddenTest t = (HiddenTest)defineHiddenClass("HiddenClass").newInstance();
110 t.test();
111
112 // sanity check
113 Class<?> c = t.getClass();
114 Class<?>[] intfs = c.getInterfaces();
115 assertTrue(c.isHidden());
116 assertFalse(c.isPrimitive());
117 assertTrue(intfs.length == 1);
118 assertTrue(intfs[0] == HiddenTest.class);
119 assertTrue(c.getCanonicalName() == null);
120
121 String hcName = "HiddenClass";
122 String hcSuffix = "0x[0-9a-f]+";
123 assertTrue(c.getName().matches(hcName + "/" + hcSuffix));
124 assertTrue(c.descriptorString().matches("L" + hcName + "." + hcSuffix + ";"), c.descriptorString());
125
126 // test array of hidden class
127 testHiddenArray(c);
128
129 // test setAccessible
130 checkSetAccessible(c, "realTest");
131 checkSetAccessible(c, "test");
132 }
133
134 // primitive class is not a hidden class
135 @Test
136 public void primitiveClass() {
137 assertFalse(int.class.isHidden());
138 assertFalse(String.class.isHidden());
229 @Test(dataProvider = "hiddenClasses")
230 public void defineHiddenClass(String name, boolean nestmate) throws Exception {
231 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
232 Class<?> hc;
233 Class<?> host;
234 if (nestmate) {
235 hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
236 host = lookup().lookupClass().getNestHost();
237 } else {
238 hc = lookup().defineHiddenClass(bytes, false).lookupClass();
239 host = hc;
240 }
241 assertTrue(hc.getNestHost() == host);
242 assertTrue(hc.getNestMembers().length == 1);
243 assertTrue(hc.getNestMembers()[0] == host);
244 }
245
246 @DataProvider(name = "emptyClasses")
247 private Object[][] emptyClasses() {
248 return new Object[][] {
249 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC },
250 new Object[] { "EmptyHiddenEnum", ACC_ENUM },
251 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT },
252 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
253 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
254 };
255 }
256
257 /*
258 * Test if an empty class with valid access flags can be created as a hidden class
259 * as long as it does not violate the restriction of a hidden class.
260 *
261 * A meaningful enum type defines constants of that enum type. So
262 * enum class containing constants of its type should not be a hidden
263 * class.
264 */
265 @Test(dataProvider = "emptyClasses")
266 public void emptyHiddenClass(String name, int accessFlags) throws Exception {
267 byte[] bytes = (accessFlags == ACC_ENUM) ? classBytes(name, Enum.class, accessFlags)
268 : classBytes(name, accessFlags);
269 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
270 switch (accessFlags) {
271 case ACC_SYNTHETIC:
272 assertTrue(hc.isSynthetic());
273 assertFalse(hc.isEnum());
274 assertFalse(hc.isAnnotation());
275 assertFalse(hc.isInterface());
276 break;
277 case ACC_ENUM:
278 assertFalse(hc.isSynthetic());
279 assertTrue(hc.isEnum());
280 assertFalse(hc.isAnnotation());
281 assertFalse(hc.isInterface());
282 break;
283 case ACC_ABSTRACT:
284 assertFalse(hc.isSynthetic());
285 assertFalse(hc.isEnum());
286 assertFalse(hc.isAnnotation());
287 assertFalse(hc.isInterface());
288 break;
289 case ACC_ABSTRACT|ACC_INTERFACE:
290 assertFalse(hc.isSynthetic());
291 assertFalse(hc.isEnum());
292 assertFalse(hc.isAnnotation());
293 assertTrue(hc.isInterface());
294 break;
295 case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
296 assertFalse(hc.isSynthetic());
297 assertFalse(hc.isEnum());
298 assertTrue(hc.isAnnotation());
299 assertTrue(hc.isInterface());
300 break;
301 default:
302 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
303 }
304 assertTrue(hc.isHidden());
305 assertTrue(hc.getModifiers() == (ACC_PUBLIC|accessFlags));
306 assertFalse(hc.isLocalClass());
307 assertFalse(hc.isMemberClass());
308 assertFalse(hc.isAnonymousClass());
309 assertFalse(hc.isArray());
310 }
311
312 // These class files can't be defined as hidden classes
313 @DataProvider(name = "cantBeHiddenClasses")
314 private Object[][] cantBeHiddenClasses() {
315 return new Object[][] {
316 // a hidden class can't be a field's declaring type
317 // enum class with static final HiddenEnum[] $VALUES:
318 new Object[] { "HiddenEnum" },
319 // supertype of this class is a hidden class
320 new Object[] { "HiddenSuper" },
321 // a record class whose equals(HiddenRecord, Object) method
322 // refers to a hidden class in the parameter type and fails
323 // verification. Perhaps this method signature should be reconsidered.
324 new Object[] { "HiddenRecord" },
325 };
|
24 /*
25 * @test
26 * @modules java.base/jdk.internal.org.objectweb.asm
27 * jdk.compiler
28 * @library /test/lib
29 * @compile BadClassFile.jcod
30 * BadClassFile2.jcod
31 * BadClassFileVersion.jcod
32 * @build jdk.test.lib.Utils
33 * jdk.test.lib.compiler.CompilerUtils
34 * @run testng/othervm BasicTest
35 */
36
37 import java.io.File;
38 import java.io.IOException;
39 import java.lang.invoke.MethodHandles.Lookup;
40
41 import static java.lang.invoke.MethodHandles.lookup;
42 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
43
44 import java.lang.reflect.AccessFlag;
45 import java.lang.reflect.Array;
46 import java.lang.reflect.Method;
47 import java.nio.charset.StandardCharsets;
48 import java.nio.file.Files;
49 import java.nio.file.Path;
50 import java.nio.file.Paths;
51 import java.util.Arrays;
52 import java.util.List;
53 import java.util.stream.Stream;
54
55 import jdk.internal.org.objectweb.asm.ClassWriter;
56 import jdk.internal.org.objectweb.asm.Type;
57 import jdk.test.lib.compiler.CompilerUtils;
58 import jdk.test.lib.Utils;
59
60 import org.testng.annotations.BeforeTest;
61 import org.testng.annotations.DataProvider;
62 import org.testng.annotations.Test;
63
64 import static jdk.internal.org.objectweb.asm.Opcodes.*;
98
99 static Class<?> defineHiddenClass(String name) throws Exception {
100 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
101 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
102 assertHiddenClass(hc);
103 singletonNest(hc);
104 return hc;
105 }
106
107 // basic test on a hidden class
108 @Test
109 public void hiddenClass() throws Throwable {
110 HiddenTest t = (HiddenTest)defineHiddenClass("HiddenClass").newInstance();
111 t.test();
112
113 // sanity check
114 Class<?> c = t.getClass();
115 Class<?>[] intfs = c.getInterfaces();
116 assertTrue(c.isHidden());
117 assertFalse(c.isPrimitive());
118 assertTrue(intfs.length == 1 || intfs.length == 2);
119 assertTrue(intfs[0] == HiddenTest.class || (intfs.length == 2 && intfs[1] == HiddenTest.class));
120 assertTrue(c.getCanonicalName() == null);
121
122 String hcName = "HiddenClass";
123 String hcSuffix = "0x[0-9a-f]+";
124 assertTrue(c.getName().matches(hcName + "/" + hcSuffix));
125 assertTrue(c.descriptorString().matches("L" + hcName + "." + hcSuffix + ";"), c.descriptorString());
126
127 // test array of hidden class
128 testHiddenArray(c);
129
130 // test setAccessible
131 checkSetAccessible(c, "realTest");
132 checkSetAccessible(c, "test");
133 }
134
135 // primitive class is not a hidden class
136 @Test
137 public void primitiveClass() {
138 assertFalse(int.class.isHidden());
139 assertFalse(String.class.isHidden());
230 @Test(dataProvider = "hiddenClasses")
231 public void defineHiddenClass(String name, boolean nestmate) throws Exception {
232 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
233 Class<?> hc;
234 Class<?> host;
235 if (nestmate) {
236 hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
237 host = lookup().lookupClass().getNestHost();
238 } else {
239 hc = lookup().defineHiddenClass(bytes, false).lookupClass();
240 host = hc;
241 }
242 assertTrue(hc.getNestHost() == host);
243 assertTrue(hc.getNestMembers().length == 1);
244 assertTrue(hc.getNestMembers()[0] == host);
245 }
246
247 @DataProvider(name = "emptyClasses")
248 private Object[][] emptyClasses() {
249 return new Object[][] {
250 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC | ACC_IDENTITY },
251 new Object[] { "EmptyHiddenEnum", ACC_ENUM | ACC_IDENTITY },
252 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT | ACC_IDENTITY },
253 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
254 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
255 };
256 }
257
258 /*
259 * Test if an empty class with valid access flags can be created as a hidden class
260 * as long as it does not violate the restriction of a hidden class.
261 *
262 * A meaningful enum type defines constants of that enum type. So
263 * enum class containing constants of its type should not be a hidden
264 * class.
265 */
266 @Test(dataProvider = "emptyClasses")
267 public void emptyHiddenClass(String name, int accessFlags) throws Exception {
268 byte[] bytes = (accessFlags == (ACC_ENUM | ACC_IDENTITY)) ? classBytes(name, Enum.class, accessFlags)
269 : classBytes(name, accessFlags);
270 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
271 switch (accessFlags) {
272 case (ACC_SYNTHETIC | ACC_IDENTITY):
273 assertTrue(hc.isSynthetic());
274 assertFalse(hc.isEnum());
275 assertFalse(hc.isAnnotation());
276 assertFalse(hc.isInterface());
277 break;
278 case (ACC_ENUM | ACC_IDENTITY):
279 assertFalse(hc.isSynthetic());
280 assertTrue(hc.isEnum());
281 assertFalse(hc.isAnnotation());
282 assertFalse(hc.isInterface());
283 break;
284 case ACC_ABSTRACT | ACC_IDENTITY:
285 assertFalse(hc.isSynthetic());
286 assertFalse(hc.isEnum());
287 assertFalse(hc.isAnnotation());
288 assertFalse(hc.isInterface());
289 break;
290 case ACC_ABSTRACT|ACC_INTERFACE:
291 assertFalse(hc.isSynthetic());
292 assertFalse(hc.isEnum());
293 assertFalse(hc.isAnnotation());
294 assertTrue(hc.isInterface());
295 break;
296 case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
297 assertFalse(hc.isSynthetic());
298 assertFalse(hc.isEnum());
299 assertTrue(hc.isAnnotation());
300 assertTrue(hc.isInterface());
301 break;
302 default:
303 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
304 }
305 assertTrue(hc.isHidden());
306 assertEquals(hc.getModifiers(), (ACC_PUBLIC|accessFlags));
307 assertFalse(hc.isLocalClass());
308 assertFalse(hc.isMemberClass());
309 assertFalse(hc.isAnonymousClass());
310 assertFalse(hc.isArray());
311 }
312
313 // These class files can't be defined as hidden classes
314 @DataProvider(name = "cantBeHiddenClasses")
315 private Object[][] cantBeHiddenClasses() {
316 return new Object[][] {
317 // a hidden class can't be a field's declaring type
318 // enum class with static final HiddenEnum[] $VALUES:
319 new Object[] { "HiddenEnum" },
320 // supertype of this class is a hidden class
321 new Object[] { "HiddenSuper" },
322 // a record class whose equals(HiddenRecord, Object) method
323 // refers to a hidden class in the parameter type and fails
324 // verification. Perhaps this method signature should be reconsidered.
325 new Object[] { "HiddenRecord" },
326 };
|