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