< prev index next >

test/jdk/java/lang/invoke/defineHiddenClass/BasicTest.java

Print this page

 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         };
< prev index next >