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