36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.Set;
43 import java.util.WeakHashMap;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.stream.Stream;
46
47 import jdk.internal.access.JavaLangReflectAccess;
48 import jdk.internal.access.SharedSecrets;
49 import java.lang.classfile.ClassHierarchyResolver;
50 import java.lang.classfile.ClassFile;
51 import java.lang.classfile.CodeBuilder;
52 import java.lang.classfile.TypeKind;
53
54 import jdk.internal.constant.ConstantUtils;
55 import jdk.internal.loader.ClassLoaders;
56 import jdk.internal.module.Modules;
57 import jdk.internal.util.ClassFileDumper;
58
59 import static java.lang.constant.ConstantDescs.*;
60 import static java.lang.invoke.MethodHandleStatics.*;
61 import static java.lang.invoke.MethodType.methodType;
62 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
63 import static java.lang.classfile.ClassFile.*;
64 import static jdk.internal.constant.ConstantUtils.*;
65
66 /**
67 * This class consists exclusively of static methods that help adapt
68 * method handles to other JVM types, such as interfaces.
69 *
70 * @since 1.7
71 */
72 public final class MethodHandleProxies {
73
74 private MethodHandleProxies() { } // do not instantiate
75
328 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
329 private static final String TARGET_NAME = "target";
330 private static final String TYPE_NAME = "interfaceType";
331 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
332
333 /**
334 * Creates an implementation class file for a given interface. One implementation class is
335 * defined for each interface.
336 *
337 * @param ifaceDesc the given interface
338 * @param methodName the name of the single abstract method
339 * @param methods the information for implementation methods
340 * @return the bytes of the implementation classes
341 */
342 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
343 String methodName, List<MethodInfo> methods) {
344 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
345 ClassLoaders.platformClassLoader() : loader)))
346 .build(proxyDesc, clb -> {
347 clb.withSuperclass(CD_Object)
348 .withFlags(ACC_FINAL | ACC_SYNTHETIC)
349 .withInterfaceSymbols(ifaceDesc)
350 // static and instance fields
351 .withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL)
352 .withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
353 for (var mi : methods) {
354 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
355 }
356
357 // <clinit>
358 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
359 cob.loadConstant(ifaceDesc)
360 .putstatic(proxyDesc, TYPE_NAME, CD_Class)
361 .return_();
362 });
363
364 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
365 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
366 cob.aload(0)
367 .invokespecial(CD_Object, INIT_NAME, MTD_void)
368 // call ensureOriginalLookup to verify the given Lookup has access
|
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.Set;
43 import java.util.WeakHashMap;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.stream.Stream;
46
47 import jdk.internal.access.JavaLangReflectAccess;
48 import jdk.internal.access.SharedSecrets;
49 import java.lang.classfile.ClassHierarchyResolver;
50 import java.lang.classfile.ClassFile;
51 import java.lang.classfile.CodeBuilder;
52 import java.lang.classfile.TypeKind;
53
54 import jdk.internal.constant.ConstantUtils;
55 import jdk.internal.loader.ClassLoaders;
56 import jdk.internal.misc.PreviewFeatures;
57 import jdk.internal.module.Modules;
58 import jdk.internal.util.ClassFileDumper;
59
60 import static java.lang.constant.ConstantDescs.*;
61 import static java.lang.invoke.MethodHandleStatics.*;
62 import static java.lang.invoke.MethodType.methodType;
63 import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
64 import static java.lang.classfile.ClassFile.*;
65 import static jdk.internal.constant.ConstantUtils.*;
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 final class MethodHandleProxies {
74
75 private MethodHandleProxies() { } // do not instantiate
76
329 private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(CD_void, CD_String);
330 private static final String TARGET_NAME = "target";
331 private static final String TYPE_NAME = "interfaceType";
332 private static final String ENSURE_ORIGINAL_LOOKUP = "ensureOriginalLookup";
333
334 /**
335 * Creates an implementation class file for a given interface. One implementation class is
336 * defined for each interface.
337 *
338 * @param ifaceDesc the given interface
339 * @param methodName the name of the single abstract method
340 * @param methods the information for implementation methods
341 * @return the bytes of the implementation classes
342 */
343 private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
344 String methodName, List<MethodInfo> methods) {
345 return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
346 ClassLoaders.platformClassLoader() : loader)))
347 .build(proxyDesc, clb -> {
348 clb.withSuperclass(CD_Object)
349 .withFlags((PreviewFeatures.isEnabled() ? ACC_IDENTITY : 0) | ACC_FINAL | ACC_SYNTHETIC)
350 .withInterfaceSymbols(ifaceDesc)
351 // static and instance fields
352 .withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL)
353 .withField(TARGET_NAME, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
354 for (var mi : methods) {
355 clb.withField(mi.fieldName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);
356 }
357
358 // <clinit>
359 clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
360 cob.loadConstant(ifaceDesc)
361 .putstatic(proxyDesc, TYPE_NAME, CD_Class)
362 .return_();
363 });
364
365 // <init>(Lookup, MethodHandle target, MethodHandle callerBoundTarget)
366 clb.withMethodBody(INIT_NAME, MTD_void_Lookup_MethodHandle_MethodHandle, 0, cob -> {
367 cob.aload(0)
368 .invokespecial(CD_Object, INIT_NAME, MTD_void)
369 // call ensureOriginalLookup to verify the given Lookup has access
|