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 jdk.internal.classfile.ClassHierarchyResolver;
52 import jdk.internal.classfile.Classfile;
53 import jdk.internal.classfile.CodeBuilder;
54 import jdk.internal.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 jdk.internal.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);
|
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 jdk.internal.classfile.ClassHierarchyResolver;
52 import jdk.internal.classfile.Classfile;
53 import jdk.internal.classfile.CodeBuilder;
54 import jdk.internal.classfile.TypeKind;
55 import jdk.internal.misc.ValhallaFeatures;
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 jdk.internal.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((ValhallaFeatures.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);
|