5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @modules java.base/java.lang:open
26 * @run junit/othervm test.DefineClassTest
27 * @summary Basic test for java.lang.invoke.MethodHandles.Lookup.defineClass
28 */
29
30 package test;
31
32 import java.lang.classfile.ClassFile;
33 import java.lang.constant.ClassDesc;
34 import java.lang.invoke.MethodHandles.Lookup;
35 import java.lang.reflect.AccessFlag;
36 import java.net.URL;
37 import java.net.URLClassLoader;
38 import java.nio.file.Files;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41
42 import static java.lang.classfile.ClassFile.ACC_PUBLIC;
43 import static java.lang.classfile.ClassFile.ACC_STATIC;
44 import static java.lang.constant.ConstantDescs.CD_Object;
232 @Test
233 public void testNull() throws Exception {
234 assertThrows(NullPointerException.class, () -> lookup().defineClass(null));
235 }
236
237 @Test
238 public void testLinking() throws Exception {
239 assertThrows(NoClassDefFoundError.class, () -> lookup().defineClass(generateNonLinkableClass(THIS_PACKAGE + ".NonLinkableClass")));
240 }
241
242 @Test
243 public void testModuleInfo() throws Exception {
244 assertThrows(IllegalArgumentException.class, () -> lookup().defineClass(generateModuleInfo()));
245 }
246
247 /**
248 * Generates a class file with the given class name
249 */
250 byte[] generateClass(String className) {
251 return ClassFile.of().build(ClassDesc.of(className), clb -> {
252 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.SUPER);
253 clb.withSuperclass(CD_Object);
254 clb.withMethodBody(INIT_NAME, MTD_void, PUBLIC, cob -> {
255 cob.aload(0);
256 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
257 cob.return_();
258 });
259 });
260 }
261
262 /**
263 * Generate a class file with the given class name. The class implements Runnable
264 * with a run method to invokestatic the given targetClass/targetMethod.
265 */
266 byte[] generateRunner(String className,
267 String targetClass,
268 String targetMethod) throws Exception {
269
270 return ClassFile.of().build(ClassDesc.of(className), clb -> {
271 clb.withSuperclass(CD_Object);
272 clb.withInterfaceSymbols(CD_Runnable);
274 cob.aload(0);
275 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
276 cob.return_();
277 });
278 clb.withMethodBody("run", MTD_void, PUBLIC, cob -> {
279 cob.invokestatic(ClassDesc.of(targetClass), targetMethod, MTD_void);
280 cob.return_();
281 });
282 });
283 }
284
285 /**
286 * Generate a class file with the given class name. The class will initializer
287 * to invokestatic the given targetClass/targetMethod.
288 */
289 byte[] generateClassWithInitializer(String className,
290 String targetClass,
291 String targetMethod) throws Exception {
292
293 return ClassFile.of().build(ClassDesc.of(className), clb -> {
294 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.SUPER);
295 clb.withSuperclass(CD_Object);
296 clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> {
297 cob.aload(0);
298 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
299 cob.return_();
300 });
301 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
302 cob.invokestatic(ClassDesc.of(targetClass), targetMethod, MTD_void);
303 cob.return_();
304 });
305 });
306 }
307
308 /**
309 * Generates a non-linkable class file with the given class name
310 */
311 byte[] generateNonLinkableClass(String className) {
312 return ClassFile.of().build(ClassDesc.of(className), clb -> {
313 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.SUPER);
314 clb.withSuperclass(CD_MissingSuperClass);
315 clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> {
316 cob.aload(0);
317 cob.invokespecial(CD_MissingSuperClass, INIT_NAME, MTD_void);
318 cob.return_();
319 });
320 });
321 }
322
323 /**
324 * Generates a class file with the given class name
325 */
326 byte[] generateModuleInfo() {
327 return ClassFile.of().build(ClassDesc.of("module-info"), cb -> cb.withFlags(AccessFlag.MODULE));
328 }
329
330 private int nextNumber() {
331 return ++nextNumber;
332 }
333
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @enablePreview
26 * @modules java.base/java.lang:open
27 * @run junit/othervm test.DefineClassTest
28 * @summary Basic test for java.lang.invoke.MethodHandles.Lookup.defineClass
29 */
30
31 package test;
32
33 import java.lang.classfile.ClassFile;
34 import java.lang.constant.ClassDesc;
35 import java.lang.invoke.MethodHandles.Lookup;
36 import java.lang.reflect.AccessFlag;
37 import java.net.URL;
38 import java.net.URLClassLoader;
39 import java.nio.file.Files;
40 import java.nio.file.Path;
41 import java.nio.file.Paths;
42
43 import static java.lang.classfile.ClassFile.ACC_PUBLIC;
44 import static java.lang.classfile.ClassFile.ACC_STATIC;
45 import static java.lang.constant.ConstantDescs.CD_Object;
233 @Test
234 public void testNull() throws Exception {
235 assertThrows(NullPointerException.class, () -> lookup().defineClass(null));
236 }
237
238 @Test
239 public void testLinking() throws Exception {
240 assertThrows(NoClassDefFoundError.class, () -> lookup().defineClass(generateNonLinkableClass(THIS_PACKAGE + ".NonLinkableClass")));
241 }
242
243 @Test
244 public void testModuleInfo() throws Exception {
245 assertThrows(IllegalArgumentException.class, () -> lookup().defineClass(generateModuleInfo()));
246 }
247
248 /**
249 * Generates a class file with the given class name
250 */
251 byte[] generateClass(String className) {
252 return ClassFile.of().build(ClassDesc.of(className), clb -> {
253 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.IDENTITY);
254 clb.withSuperclass(CD_Object);
255 clb.withMethodBody(INIT_NAME, MTD_void, PUBLIC, cob -> {
256 cob.aload(0);
257 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
258 cob.return_();
259 });
260 });
261 }
262
263 /**
264 * Generate a class file with the given class name. The class implements Runnable
265 * with a run method to invokestatic the given targetClass/targetMethod.
266 */
267 byte[] generateRunner(String className,
268 String targetClass,
269 String targetMethod) throws Exception {
270
271 return ClassFile.of().build(ClassDesc.of(className), clb -> {
272 clb.withSuperclass(CD_Object);
273 clb.withInterfaceSymbols(CD_Runnable);
275 cob.aload(0);
276 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
277 cob.return_();
278 });
279 clb.withMethodBody("run", MTD_void, PUBLIC, cob -> {
280 cob.invokestatic(ClassDesc.of(targetClass), targetMethod, MTD_void);
281 cob.return_();
282 });
283 });
284 }
285
286 /**
287 * Generate a class file with the given class name. The class will initializer
288 * to invokestatic the given targetClass/targetMethod.
289 */
290 byte[] generateClassWithInitializer(String className,
291 String targetClass,
292 String targetMethod) throws Exception {
293
294 return ClassFile.of().build(ClassDesc.of(className), clb -> {
295 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.IDENTITY);
296 clb.withSuperclass(CD_Object);
297 clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> {
298 cob.aload(0);
299 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
300 cob.return_();
301 });
302 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
303 cob.invokestatic(ClassDesc.of(targetClass), targetMethod, MTD_void);
304 cob.return_();
305 });
306 });
307 }
308
309 /**
310 * Generates a non-linkable class file with the given class name
311 */
312 byte[] generateNonLinkableClass(String className) {
313 return ClassFile.of().build(ClassDesc.of(className), clb -> {
314 clb.withFlags(AccessFlag.PUBLIC, AccessFlag.IDENTITY);
315 clb.withSuperclass(CD_MissingSuperClass);
316 clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> {
317 cob.aload(0);
318 cob.invokespecial(CD_MissingSuperClass, INIT_NAME, MTD_void);
319 cob.return_();
320 });
321 });
322 }
323
324 /**
325 * Generates a class file with the given class name
326 */
327 byte[] generateModuleInfo() {
328 return ClassFile.of().build(ClassDesc.of("module-info"), cb -> cb.withFlags(AccessFlag.MODULE));
329 }
330
331 private int nextNumber() {
332 return ++nextNumber;
333 }
334
|