1 /*
2 * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 import java.lang.reflect.UndeclaredThrowableException;
36 import java.security.AccessController;
37 import java.security.PrivilegedAction;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Objects;
44 import java.util.Set;
45 import java.util.WeakHashMap;
46 import java.util.concurrent.atomic.AtomicInteger;
47 import java.util.stream.Stream;
48
49 import jdk.internal.access.JavaLangReflectAccess;
50 import jdk.internal.access.SharedSecrets;
51 import java.lang.classfile.ClassHierarchyResolver;
52 import java.lang.classfile.ClassFile;
53 import java.lang.classfile.CodeBuilder;
54 import java.lang.classfile.TypeKind;
55 import jdk.internal.module.Modules;
56 import jdk.internal.reflect.CallerSensitive;
57 import jdk.internal.reflect.Reflection;
58 import jdk.internal.util.ClassFileDumper;
59 import sun.reflect.misc.ReflectUtil;
60
61 import static java.lang.constant.ConstantDescs.*;
62 import static java.lang.invoke.MethodHandleStatics.*;
63 import static java.lang.invoke.MethodType.methodType;
64 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
65 import static java.lang.classfile.ClassFile.*;
66
67 /**
68 * This class consists exclusively of static methods that help adapt
69 * method handles to other JVM types, such as interfaces.
70 *
71 * @since 1.7
72 */
73 public class MethodHandleProxies {
74
353 private static final MethodTypeDesc MTD_String = MethodTypeDesc.of(CD_String);
354 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
355 private static final String TARGET_NAME = "target";
356 private static final String TYPE_NAME = "interfaceType";
357 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
358
359 /**
360 * Creates an implementation class file for a given interface. One implementation class is
361 * defined for each interface.
362 *
363 * @param ifaceDesc the given interface
364 * @param methodName the name of the single abstract method
365 * @param methods the information for implementation methods
366 * @return the bytes of the implementation classes
367 */
368 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
369 String methodName, List<MethodInfo> methods) {
370 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader)))
371 .build(proxyDesc, clb -> {
372 clb.withSuperclass(CD_Object);
373 clb.withFlags(ACC_FINAL | ACC_SYNTHETIC);
374 clb.withInterfaceSymbols(ifaceDesc);
375
376 // static and instance fields
377 clb.withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL);
378 clb.withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
379 for (var mi : methods) {
380 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
381 }
382
383 // <clinit>
384 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
385 cob.constantInstruction(ifaceDesc);
386 cob.putstatic(proxyDesc, TYPE_NAME, CD_Class);
387 cob.return_();
388 });
389
390 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
391 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
392 cob.aload(0);
393 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
|
1 /*
2 * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 import java.lang.reflect.UndeclaredThrowableException;
36 import java.security.AccessController;
37 import java.security.PrivilegedAction;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Objects;
44 import java.util.Set;
45 import java.util.WeakHashMap;
46 import java.util.concurrent.atomic.AtomicInteger;
47 import java.util.stream.Stream;
48
49 import jdk.internal.access.JavaLangReflectAccess;
50 import jdk.internal.access.SharedSecrets;
51 import java.lang.classfile.ClassHierarchyResolver;
52 import java.lang.classfile.ClassFile;
53 import java.lang.classfile.CodeBuilder;
54 import java.lang.classfile.TypeKind;
55 import jdk.internal.misc.PreviewFeatures;
56 import jdk.internal.module.Modules;
57 import jdk.internal.reflect.CallerSensitive;
58 import jdk.internal.reflect.Reflection;
59 import jdk.internal.util.ClassFileDumper;
60 import sun.reflect.misc.ReflectUtil;
61
62 import static java.lang.constant.ConstantDescs.*;
63 import static java.lang.invoke.MethodHandleStatics.*;
64 import static java.lang.invoke.MethodType.methodType;
65 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
66 import static java.lang.classfile.ClassFile.*;
67
68 /**
69 * This class consists exclusively of static methods that help adapt
70 * method handles to other JVM types, such as interfaces.
71 *
72 * @since 1.7
73 */
74 public class MethodHandleProxies {
75
354 private static final MethodTypeDesc MTD_String = MethodTypeDesc.of(CD_String);
355 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
356 private static final String TARGET_NAME = "target";
357 private static final String TYPE_NAME = "interfaceType";
358 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
359
360 /**
361 * Creates an implementation class file for a given interface. One implementation class is
362 * defined for each interface.
363 *
364 * @param ifaceDesc the given interface
365 * @param methodName the name of the single abstract method
366 * @param methods the information for implementation methods
367 * @return the bytes of the implementation classes
368 */
369 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
370 String methodName, List<MethodInfo> methods) {
371 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader)))
372 .build(proxyDesc, clb -> {
373 clb.withSuperclass(CD_Object);
374 clb.withFlags((PreviewFeatures.isEnabled() ? ACC_IDENTITY : 0) | ACC_FINAL | ACC_SYNTHETIC);
375 clb.withInterfaceSymbols(ifaceDesc);
376
377 // static and instance fields
378 clb.withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL);
379 clb.withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
380 for (var mi : methods) {
381 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
382 }
383
384 // <clinit>
385 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
386 cob.constantInstruction(ifaceDesc);
387 cob.putstatic(proxyDesc, TYPE_NAME, CD_Class);
388 cob.return_();
389 });
390
391 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
392 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
393 cob.aload(0);
394 cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
|