< prev index next >

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

Print this page

 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 junit/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 static java.lang.classfile.ClassFile.*;
 56 import static java.lang.constant.ConstantDescs.CD_Enum;
 57 import static java.lang.constant.ConstantDescs.CD_Object;
 58 import static java.lang.invoke.MethodHandles.lookup;
 59 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
 60 import static org.junit.jupiter.api.Assertions.*;
 61 import org.junit.jupiter.api.BeforeAll;

 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         assertEquals(1, intfs.length);
118         assertSame(HiddenTest.class, intfs[0]);
119         assertNull(c.getCanonicalName());
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());

232     @ParameterizedTest
233     @MethodSource("hiddenClasses")
234     public void defineHiddenClass(String name, boolean nestmate) throws Exception {
235         byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
236         Class<?> hc;
237         Class<?> host;
238         if (nestmate) {
239             hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
240             host = lookup().lookupClass().getNestHost();
241         } else {
242             hc = lookup().defineHiddenClass(bytes, false).lookupClass();
243             host = hc;
244         }
245         assertSame(host, hc.getNestHost());
246         assertEquals(1, hc.getNestMembers().length);
247         assertSame(host, hc.getNestMembers()[0]);
248     }
249 
250     private static Object[][] emptyClasses() {
251         return new Object[][] {
252                 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC },
253                 new Object[] { "EmptyHiddenEnum", ACC_ENUM },
254                 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT },
255                 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
256                 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
257         };
258     }
259 
260     /*
261      * Test if an empty class with valid access flags can be created as a hidden class
262      * as long as it does not violate the restriction of a hidden class.
263      *
264      * A meaningful enum type defines constants of that enum type.  So
265      * enum class containing constants of its type should not be a hidden
266      * class.
267      */
268     @ParameterizedTest
269     @MethodSource("emptyClasses")
270     public void emptyHiddenClass(String name, int accessFlags) throws Exception {
271         byte[] bytes = (accessFlags == ACC_ENUM) ? classBytes(name, CD_Enum, accessFlags)
272                 : classBytes(name, accessFlags);
273         Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
274         switch (accessFlags) {
275             case ACC_SYNTHETIC:
276                 assertTrue(hc.isSynthetic());
277                 assertFalse(hc.isEnum());
278                 assertFalse(hc.isAnnotation());
279                 assertFalse(hc.isInterface());
280                 break;
281             case ACC_ENUM:
282                 assertFalse(hc.isSynthetic());
283                 assertTrue(hc.isEnum());
284                 assertFalse(hc.isAnnotation());
285                 assertFalse(hc.isInterface());
286                 break;
287             case ACC_ABSTRACT:
288                 assertFalse(hc.isSynthetic());
289                 assertFalse(hc.isEnum());
290                 assertFalse(hc.isAnnotation());
291                 assertFalse(hc.isInterface());
292                 break;
293             case ACC_ABSTRACT|ACC_INTERFACE:
294                 assertFalse(hc.isSynthetic());
295                 assertFalse(hc.isEnum());
296                 assertFalse(hc.isAnnotation());
297                 assertTrue(hc.isInterface());
298                 break;
299             case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
300                 assertFalse(hc.isSynthetic());
301                 assertFalse(hc.isEnum());
302                 assertTrue(hc.isAnnotation());
303                 assertTrue(hc.isInterface());
304                 break;
305             default:
306                 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
307         }
308         assertTrue(hc.isHidden());
309         assertEquals(hc.getModifiers(), ACC_PUBLIC | accessFlags);
310         assertFalse(hc.isLocalClass());
311         assertFalse(hc.isMemberClass());
312         assertFalse(hc.isAnonymousClass());
313         assertFalse(hc.isArray());
314     }
315 
316     // These class files can't be defined as hidden classes
317     private static Object[][] cantBeHiddenClasses() {
318         return new Object[][] {
319                 // a hidden class can't be a field's declaring type
320                 // enum class with static final HiddenEnum[] $VALUES:
321                 new Object[] { "HiddenEnum" },
322                 // supertype of this class is a hidden class
323                 new Object[] { "HiddenSuper" },
324                 // a record class whose equals(HiddenRecord, Object) method
325                 // refers to a hidden class in the parameter type and fails
326                 // verification.  Perhaps this method signature should be reconsidered.
327                 new Object[] { "HiddenRecord" },
328         };
329     }

 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 junit/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 static java.lang.classfile.ClassFile.*;
 57 import static java.lang.constant.ConstantDescs.CD_Enum;
 58 import static java.lang.constant.ConstantDescs.CD_Object;
 59 import static java.lang.invoke.MethodHandles.lookup;
 60 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
 61 import static org.junit.jupiter.api.Assertions.*;
 62 import org.junit.jupiter.api.BeforeAll;

 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         assertNull(c.getCanonicalName());
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());

233     @ParameterizedTest
234     @MethodSource("hiddenClasses")
235     public void defineHiddenClass(String name, boolean nestmate) throws Exception {
236         byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
237         Class<?> hc;
238         Class<?> host;
239         if (nestmate) {
240             hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
241             host = lookup().lookupClass().getNestHost();
242         } else {
243             hc = lookup().defineHiddenClass(bytes, false).lookupClass();
244             host = hc;
245         }
246         assertSame(host, hc.getNestHost());
247         assertEquals(1, hc.getNestMembers().length);
248         assertSame(host, hc.getNestMembers()[0]);
249     }
250 
251     private static Object[][] emptyClasses() {
252         return new Object[][] {
253                 new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC | ACC_IDENTITY },
254                 new Object[] { "EmptyHiddenEnum", ACC_ENUM | ACC_IDENTITY },
255                 new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT | ACC_IDENTITY },
256                 new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
257                 new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
258         };
259     }
260 
261     /*
262      * Test if an empty class with valid access flags can be created as a hidden class
263      * as long as it does not violate the restriction of a hidden class.
264      *
265      * A meaningful enum type defines constants of that enum type.  So
266      * enum class containing constants of its type should not be a hidden
267      * class.
268      */
269     @ParameterizedTest
270     @MethodSource("emptyClasses")
271     public void emptyHiddenClass(String name, int accessFlags) throws Exception {
272         byte[] bytes = (accessFlags == (ACC_ENUM | ACC_IDENTITY)) ? classBytes(name, CD_Enum, accessFlags)
273                 : classBytes(name, accessFlags);
274         Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
275         switch (accessFlags) {
276             case (ACC_SYNTHETIC | ACC_IDENTITY):
277                 assertTrue(hc.isSynthetic());
278                 assertFalse(hc.isEnum());
279                 assertFalse(hc.isAnnotation());
280                 assertFalse(hc.isInterface());
281                 break;
282             case (ACC_ENUM | ACC_IDENTITY):
283                 assertFalse(hc.isSynthetic());
284                 assertTrue(hc.isEnum());
285                 assertFalse(hc.isAnnotation());
286                 assertFalse(hc.isInterface());
287                 break;
288             case ACC_ABSTRACT | ACC_IDENTITY:
289                 assertFalse(hc.isSynthetic());
290                 assertFalse(hc.isEnum());
291                 assertFalse(hc.isAnnotation());
292                 assertFalse(hc.isInterface());
293                 break;
294             case ACC_ABSTRACT|ACC_INTERFACE:
295                 assertFalse(hc.isSynthetic());
296                 assertFalse(hc.isEnum());
297                 assertFalse(hc.isAnnotation());
298                 assertTrue(hc.isInterface());
299                 break;
300             case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
301                 assertFalse(hc.isSynthetic());
302                 assertFalse(hc.isEnum());
303                 assertTrue(hc.isAnnotation());
304                 assertTrue(hc.isInterface());
305                 break;
306             default:
307                 throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
308         }
309         assertTrue(hc.isHidden());
310         assertEquals(hc.getModifiers(), (ACC_PUBLIC|accessFlags));
311         assertFalse(hc.isLocalClass());
312         assertFalse(hc.isMemberClass());
313         assertFalse(hc.isAnonymousClass());
314         assertFalse(hc.isArray());
315     }
316 
317     // These class files can't be defined as hidden classes
318     private static Object[][] cantBeHiddenClasses() {
319         return new Object[][] {
320                 // a hidden class can't be a field's declaring type
321                 // enum class with static final HiddenEnum[] $VALUES:
322                 new Object[] { "HiddenEnum" },
323                 // supertype of this class is a hidden class
324                 new Object[] { "HiddenSuper" },
325                 // a record class whose equals(HiddenRecord, Object) method
326                 // refers to a hidden class in the parameter type and fails
327                 // verification.  Perhaps this method signature should be reconsidered.
328                 new Object[] { "HiddenRecord" },
329         };
330     }
< prev index next >