< prev index next >

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

Print this page

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