22 */
23
24 /*
25 * @test
26 * @bug 8330467
27 * @modules 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.classfile.ClassFile;
40 import java.lang.constant.ClassDesc;
41 import java.lang.invoke.MethodHandles.Lookup;
42 import java.lang.reflect.Array;
43 import java.lang.reflect.Method;
44 import java.nio.charset.StandardCharsets;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.nio.file.Paths;
48 import java.util.Arrays;
49 import java.util.List;
50 import java.util.stream.Stream;
51
52 import jdk.test.lib.compiler.CompilerUtils;
53 import jdk.test.lib.Utils;
54
55 import org.testng.annotations.BeforeTest;
56 import org.testng.annotations.DataProvider;
57 import org.testng.annotations.Test;
58
59 import static java.lang.classfile.ClassFile.*;
60 import static java.lang.constant.ConstantDescs.CD_Enum;
61 import static java.lang.constant.ConstantDescs.CD_Object;
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());
243 @Test(dataProvider = "hiddenClasses")
244 public void defineHiddenClass(String name, boolean nestmate) throws Exception {
245 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
246 Class<?> hc;
247 Class<?> host;
248 if (nestmate) {
249 hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
250 host = lookup().lookupClass().getNestHost();
251 } else {
252 hc = lookup().defineHiddenClass(bytes, false).lookupClass();
253 host = hc;
254 }
255 assertTrue(hc.getNestHost() == host);
256 assertTrue(hc.getNestMembers().length == 1);
257 assertTrue(hc.getNestMembers()[0] == host);
258 }
259
260 @DataProvider(name = "emptyClasses")
261 private Object[][] emptyClasses() {
262 return new Object[][] {
263 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC },
264 new Object[] { "EmptyHiddenEnum", ACC_ENUM },
265 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT },
266 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
267 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
268 };
269 }
270
271 /*
272 * Test if an empty class with valid access flags can be created as a hidden class
273 * as long as it does not violate the restriction of a hidden class.
274 *
275 * A meaningful enum type defines constants of that enum type. So
276 * enum class containing constants of its type should not be a hidden
277 * class.
278 */
279 @Test(dataProvider = "emptyClasses")
280 public void emptyHiddenClass(String name, int accessFlags) throws Exception {
281 byte[] bytes = (accessFlags == ACC_ENUM) ? classBytes(name, CD_Enum, accessFlags)
282 : classBytes(name, accessFlags);
283 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
284 switch (accessFlags) {
285 case ACC_SYNTHETIC:
286 assertTrue(hc.isSynthetic());
287 assertFalse(hc.isEnum());
288 assertFalse(hc.isAnnotation());
289 assertFalse(hc.isInterface());
290 break;
291 case ACC_ENUM:
292 assertFalse(hc.isSynthetic());
293 assertTrue(hc.isEnum());
294 assertFalse(hc.isAnnotation());
295 assertFalse(hc.isInterface());
296 break;
297 case ACC_ABSTRACT:
298 assertFalse(hc.isSynthetic());
299 assertFalse(hc.isEnum());
300 assertFalse(hc.isAnnotation());
301 assertFalse(hc.isInterface());
302 break;
303 case ACC_ABSTRACT|ACC_INTERFACE:
304 assertFalse(hc.isSynthetic());
305 assertFalse(hc.isEnum());
306 assertFalse(hc.isAnnotation());
307 assertTrue(hc.isInterface());
308 break;
309 case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
310 assertFalse(hc.isSynthetic());
311 assertFalse(hc.isEnum());
312 assertTrue(hc.isAnnotation());
313 assertTrue(hc.isInterface());
314 break;
315 default:
316 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
317 }
318 assertTrue(hc.isHidden());
319 assertTrue(hc.getModifiers() == (ACC_PUBLIC|accessFlags));
320 assertFalse(hc.isLocalClass());
321 assertFalse(hc.isMemberClass());
322 assertFalse(hc.isAnonymousClass());
323 assertFalse(hc.isArray());
324 }
325
326 // These class files can't be defined as hidden classes
327 @DataProvider(name = "cantBeHiddenClasses")
328 private Object[][] cantBeHiddenClasses() {
329 return new Object[][] {
330 // a hidden class can't be a field's declaring type
331 // enum class with static final HiddenEnum[] $VALUES:
332 new Object[] { "HiddenEnum" },
333 // supertype of this class is a hidden class
334 new Object[] { "HiddenSuper" },
335 // a record class whose equals(HiddenRecord, Object) method
336 // refers to a hidden class in the parameter type and fails
337 // verification. Perhaps this method signature should be reconsidered.
338 new Object[] { "HiddenRecord" },
339 };
|
22 */
23
24 /*
25 * @test
26 * @bug 8330467
27 * @modules 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.classfile.ClassFile;
40 import java.lang.constant.ClassDesc;
41 import java.lang.invoke.MethodHandles.Lookup;
42 import java.lang.reflect.AccessFlag;
43 import java.lang.reflect.Array;
44 import java.lang.reflect.Method;
45 import java.nio.charset.StandardCharsets;
46 import java.nio.file.Files;
47 import java.nio.file.Path;
48 import java.nio.file.Paths;
49 import java.util.Arrays;
50 import java.util.List;
51 import java.util.stream.Stream;
52
53 import jdk.test.lib.compiler.CompilerUtils;
54 import jdk.test.lib.Utils;
55
56 import org.testng.annotations.BeforeTest;
57 import org.testng.annotations.DataProvider;
58 import org.testng.annotations.Test;
59
60 import static java.lang.classfile.ClassFile.*;
61 import static java.lang.constant.ConstantDescs.CD_Enum;
62 import static java.lang.constant.ConstantDescs.CD_Object;
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());
244 @Test(dataProvider = "hiddenClasses")
245 public void defineHiddenClass(String name, boolean nestmate) throws Exception {
246 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
247 Class<?> hc;
248 Class<?> host;
249 if (nestmate) {
250 hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
251 host = lookup().lookupClass().getNestHost();
252 } else {
253 hc = lookup().defineHiddenClass(bytes, false).lookupClass();
254 host = hc;
255 }
256 assertTrue(hc.getNestHost() == host);
257 assertTrue(hc.getNestMembers().length == 1);
258 assertTrue(hc.getNestMembers()[0] == host);
259 }
260
261 @DataProvider(name = "emptyClasses")
262 private Object[][] emptyClasses() {
263 return new Object[][] {
264 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC | ACC_IDENTITY },
265 new Object[] { "EmptyHiddenEnum", ACC_ENUM | ACC_IDENTITY },
266 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT | ACC_IDENTITY },
267 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
268 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
269 };
270 }
271
272 /*
273 * Test if an empty class with valid access flags can be created as a hidden class
274 * as long as it does not violate the restriction of a hidden class.
275 *
276 * A meaningful enum type defines constants of that enum type. So
277 * enum class containing constants of its type should not be a hidden
278 * class.
279 */
280 @Test(dataProvider = "emptyClasses")
281 public void emptyHiddenClass(String name, int accessFlags) throws Exception {
282 byte[] bytes = (accessFlags == (ACC_ENUM | ACC_IDENTITY)) ? classBytes(name, CD_Enum, accessFlags)
283 : classBytes(name, accessFlags);
284 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
285 switch (accessFlags) {
286 case (ACC_SYNTHETIC | ACC_IDENTITY):
287 assertTrue(hc.isSynthetic());
288 assertFalse(hc.isEnum());
289 assertFalse(hc.isAnnotation());
290 assertFalse(hc.isInterface());
291 break;
292 case (ACC_ENUM | ACC_IDENTITY):
293 assertFalse(hc.isSynthetic());
294 assertTrue(hc.isEnum());
295 assertFalse(hc.isAnnotation());
296 assertFalse(hc.isInterface());
297 break;
298 case ACC_ABSTRACT | ACC_IDENTITY:
299 assertFalse(hc.isSynthetic());
300 assertFalse(hc.isEnum());
301 assertFalse(hc.isAnnotation());
302 assertFalse(hc.isInterface());
303 break;
304 case ACC_ABSTRACT|ACC_INTERFACE:
305 assertFalse(hc.isSynthetic());
306 assertFalse(hc.isEnum());
307 assertFalse(hc.isAnnotation());
308 assertTrue(hc.isInterface());
309 break;
310 case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
311 assertFalse(hc.isSynthetic());
312 assertFalse(hc.isEnum());
313 assertTrue(hc.isAnnotation());
314 assertTrue(hc.isInterface());
315 break;
316 default:
317 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
318 }
319 assertTrue(hc.isHidden());
320 assertEquals(hc.getModifiers(), (ACC_PUBLIC|accessFlags));
321 assertFalse(hc.isLocalClass());
322 assertFalse(hc.isMemberClass());
323 assertFalse(hc.isAnonymousClass());
324 assertFalse(hc.isArray());
325 }
326
327 // These class files can't be defined as hidden classes
328 @DataProvider(name = "cantBeHiddenClasses")
329 private Object[][] cantBeHiddenClasses() {
330 return new Object[][] {
331 // a hidden class can't be a field's declaring type
332 // enum class with static final HiddenEnum[] $VALUES:
333 new Object[] { "HiddenEnum" },
334 // supertype of this class is a hidden class
335 new Object[] { "HiddenSuper" },
336 // a record class whose equals(HiddenRecord, Object) method
337 // refers to a hidden class in the parameter type and fails
338 // verification. Perhaps this method signature should be reconsidered.
339 new Object[] { "HiddenRecord" },
340 };
|