< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java

Print this page

  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);
< prev index next >