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
56 import jdk.internal.constant.ConstantUtils;
57 import jdk.internal.loader.ClassLoaders;
58 import jdk.internal.module.Modules;
59 import jdk.internal.reflect.CallerSensitive;
60 import jdk.internal.reflect.Reflection;
61 import jdk.internal.util.ClassFileDumper;
62 import sun.reflect.misc.ReflectUtil;
63
64 import static java.lang.constant.ConstantDescs.*;
65 import static java.lang.invoke.MethodHandleStatics.*;
66 import static java.lang.invoke.MethodType.methodType;
67 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
68 import static java.lang.classfile.ClassFile.*;
69 import static jdk.internal.constant.ConstantUtils.*;
70
71 /**
72 * This class consists exclusively of static methods that help adapt
73 * method handles to other JVM types, such as interfaces.
74 *
75 * @since 1.7
76 */
77 public class MethodHandleProxies {
359 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
360 private static final String TARGET_NAME = "target";
361 private static final String TYPE_NAME = "interfaceType";
362 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
363
364 /**
365 * Creates an implementation class file for a given interface. One implementation class is
366 * defined for each interface.
367 *
368 * @param ifaceDesc the given interface
369 * @param methodName the name of the single abstract method
370 * @param methods the information for implementation methods
371 * @return the bytes of the implementation classes
372 */
373 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
374 String methodName, List<MethodInfo> methods) {
375 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
376 ClassLoaders.platformClassLoader() : loader)))
377 .build(proxyDesc, clb -> {
378 clb.withSuperclass(CD_Object)
379 .withFlags(ACC_FINAL | ACC_SYNTHETIC)
380 .withInterfaceSymbols(ifaceDesc)
381 // static and instance fields
382 .withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL)
383 .withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
384 for (var mi : methods) {
385 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
386 }
387
388 // <clinit>
389 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
390 cob.loadConstant(ifaceDesc)
391 .putstatic(proxyDesc, TYPE_NAME, CD_Class)
392 .return_();
393 });
394
395 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
396 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
397 cob.aload(0)
398 .invokespecial(CD_Object, INIT_NAME, MTD_void)
399 // call ensureOriginalLookup to verify the given Lookup has access
|
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
56 import jdk.internal.constant.ConstantUtils;
57 import jdk.internal.loader.ClassLoaders;
58 import jdk.internal.misc.PreviewFeatures;
59 import jdk.internal.module.Modules;
60 import jdk.internal.reflect.CallerSensitive;
61 import jdk.internal.reflect.Reflection;
62 import jdk.internal.util.ClassFileDumper;
63 import sun.reflect.misc.ReflectUtil;
64
65 import static java.lang.constant.ConstantDescs.*;
66 import static java.lang.invoke.MethodHandleStatics.*;
67 import static java.lang.invoke.MethodType.methodType;
68 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
69 import static java.lang.classfile.ClassFile.*;
70 import static jdk.internal.constant.ConstantUtils.*;
71
72 /**
73 * This class consists exclusively of static methods that help adapt
74 * method handles to other JVM types, such as interfaces.
75 *
76 * @since 1.7
77 */
78 public class MethodHandleProxies {
360 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
361 private static final String TARGET_NAME = "target";
362 private static final String TYPE_NAME = "interfaceType";
363 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
364
365 /**
366 * Creates an implementation class file for a given interface. One implementation class is
367 * defined for each interface.
368 *
369 * @param ifaceDesc the given interface
370 * @param methodName the name of the single abstract method
371 * @param methods the information for implementation methods
372 * @return the bytes of the implementation classes
373 */
374 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
375 String methodName, List<MethodInfo> methods) {
376 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
377 ClassLoaders.platformClassLoader() : loader)))
378 .build(proxyDesc, clb -> {
379 clb.withSuperclass(CD_Object)
380 .withFlags((PreviewFeatures.isEnabled() ? ACC_IDENTITY : 0) | ACC_FINAL | ACC_SYNTHETIC)
381 .withInterfaceSymbols(ifaceDesc)
382 // static and instance fields
383 .withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL)
384 .withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
385 for (var mi : methods) {
386 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
387 }
388
389 // <clinit>
390 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
391 cob.loadConstant(ifaceDesc)
392 .putstatic(proxyDesc, TYPE_NAME, CD_Class)
393 .return_();
394 });
395
396 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
397 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
398 cob.aload(0)
399 .invokespecial(CD_Object, INIT_NAME, MTD_void)
400 // call ensureOriginalLookup to verify the given Lookup has access
|