< prev index next >

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

Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com


  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
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.access.JavaLangInvokeAccess;
  29 import jdk.internal.access.SharedSecrets;
  30 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  31 import jdk.internal.org.objectweb.asm.ClassWriter;
  32 import jdk.internal.org.objectweb.asm.MethodVisitor;
  33 import jdk.internal.reflect.CallerSensitive;
  34 import jdk.internal.reflect.Reflection;
  35 import jdk.internal.vm.annotation.ForceInline;
  36 import jdk.internal.vm.annotation.Hidden;
  37 import jdk.internal.vm.annotation.Stable;
  38 import sun.invoke.empty.Empty;
  39 import sun.invoke.util.ValueConversions;
  40 import sun.invoke.util.VerifyType;
  41 import sun.invoke.util.Wrapper;
  42 

  43 import java.lang.reflect.Array;
  44 import java.nio.ByteOrder;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.HashMap;
  48 import java.util.Iterator;
  49 import java.util.List;
  50 import java.util.Map;
  51 import java.util.function.Function;
  52 import java.util.stream.Stream;
  53 
  54 import static java.lang.invoke.LambdaForm.*;
  55 import static java.lang.invoke.MethodHandleStatics.*;
  56 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  57 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  58 
  59 /**
  60  * Trusted implementation code for MethodHandle.
  61  * @author jrose
  62  */


1140         private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1141 
1142         static MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1143             // Code in the boot layer should now be careful while creating method handles or
1144             // functional interface instances created from method references to @CallerSensitive  methods,
1145             // it needs to be ensured the handles or interface instances are kept safe and are not passed
1146             // from the boot layer to untrusted code.
1147             if (hostClass == null
1148                 ||    (hostClass.isArray() ||
1149                        hostClass.isPrimitive() ||
1150                        hostClass.getName().startsWith("java.lang.invoke."))) {
1151                 throw new InternalError();  // does not happen, and should not anyway
1152             }
1153             // For simplicity, convert mh to a varargs-like method.
1154             MethodHandle vamh = prepareForInvoker(mh);
1155             // Cache the result of makeInjectedInvoker once per argument class.
1156             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1157             return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1158         }
1159 
1160         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
1161             try {
1162                 Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null);
1163                 assert checkInjectedInvoker(hostClass, invokerClass);














1164                 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1165             } catch (ReflectiveOperationException ex) {
1166                 throw uncaughtException(ex);
1167             }
1168         }
1169 
1170         private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1171             @Override protected MethodHandle computeValue(Class<?> hostClass) {
1172                 return makeInjectedInvoker(hostClass);
1173             }
1174         };
1175 
1176         // Adapt mh so that it can be called directly from an injected invoker:
1177         private static MethodHandle prepareForInvoker(MethodHandle mh) {
1178             mh = mh.asFixedArity();
1179             MethodType mt = mh.type();
1180             int arity = mt.parameterCount();
1181             MethodHandle vamh = mh.asType(mt.generic());
1182             vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
1183             vamh = vamh.asSpreader(Object[].class, arity);


1239         }
1240 
1241         private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate();
1242 
1243         /** Produces byte code for a class that is used as an injected invoker. */
1244         private static byte[] generateInvokerTemplate() {
1245             ClassWriter cw = new ClassWriter(0);
1246 
1247             // private static class InjectedInvoker {
1248             //     @Hidden
1249             //     static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
1250             //        return vamh.invokeExact(args);
1251             //     }
1252             // }
1253             cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null);
1254 
1255             MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V",
1256                           "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;",
1257                           null, null);
1258 
1259             // Suppress invoker method in stack traces.
1260             AnnotationVisitor av0 = mv.visitAnnotation(InvokerBytecodeGenerator.HIDDEN_SIG, true);
1261             av0.visitEnd();
1262 
1263             mv.visitCode();
1264             mv.visitVarInsn(ALOAD, 0);
1265             mv.visitVarInsn(ALOAD, 1);
1266             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact",
1267                                "([Ljava/lang/Object;)Ljava/lang/Object;", false);
1268             mv.visitInsn(ARETURN);
1269             mv.visitMaxs(2, 2);
1270             mv.visitEnd();
1271 
1272             cw.visitEnd();
1273             return cw.toByteArray();
1274         }
1275     }
1276 
1277     /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
1278     private static final class WrappedMember extends DelegatingMethodHandle {
1279         private final MethodHandle target;
1280         private final MemberName member;
1281         private final Class<?> callerClass;
1282         private final boolean isInvokeSpecial;




  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
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.access.JavaLangInvokeAccess;
  29 import jdk.internal.access.SharedSecrets;

  30 import jdk.internal.org.objectweb.asm.ClassWriter;
  31 import jdk.internal.org.objectweb.asm.MethodVisitor;
  32 import jdk.internal.reflect.CallerSensitive;
  33 import jdk.internal.reflect.Reflection;
  34 import jdk.internal.vm.annotation.ForceInline;
  35 import jdk.internal.vm.annotation.Hidden;
  36 import jdk.internal.vm.annotation.Stable;
  37 import sun.invoke.empty.Empty;
  38 import sun.invoke.util.ValueConversions;
  39 import sun.invoke.util.VerifyType;
  40 import sun.invoke.util.Wrapper;
  41 
  42 import java.lang.invoke.MethodHandles.Lookup;
  43 import java.lang.reflect.Array;
  44 import java.nio.ByteOrder;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.HashMap;
  48 import java.util.Iterator;
  49 import java.util.List;
  50 import java.util.Map;
  51 import java.util.function.Function;
  52 import java.util.stream.Stream;
  53 
  54 import static java.lang.invoke.LambdaForm.*;
  55 import static java.lang.invoke.MethodHandleStatics.*;
  56 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  57 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  58 
  59 /**
  60  * Trusted implementation code for MethodHandle.
  61  * @author jrose
  62  */


1140         private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1141 
1142         static MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1143             // Code in the boot layer should now be careful while creating method handles or
1144             // functional interface instances created from method references to @CallerSensitive  methods,
1145             // it needs to be ensured the handles or interface instances are kept safe and are not passed
1146             // from the boot layer to untrusted code.
1147             if (hostClass == null
1148                 ||    (hostClass.isArray() ||
1149                        hostClass.isPrimitive() ||
1150                        hostClass.getName().startsWith("java.lang.invoke."))) {
1151                 throw new InternalError();  // does not happen, and should not anyway
1152             }
1153             // For simplicity, convert mh to a varargs-like method.
1154             MethodHandle vamh = prepareForInvoker(mh);
1155             // Cache the result of makeInjectedInvoker once per argument class.
1156             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1157             return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1158         }
1159 
1160         private static MethodHandle makeInjectedInvoker(Class<?> targetClass) {
1161             try {
1162                 /*
1163                  * The invoker class defined to the same class loader as the lookup class
1164                  * but in an unnamed package so that the class bytes can be cached and
1165                  * reused for any @CSM.
1166                  *
1167                  * @CSM must be public and exported if called by any module.
1168                  */
1169                 String name = targetClass.getName() + "$$InjectedInvoker";
1170                 if (targetClass.isHiddenClass()) {
1171                     // use the original class name
1172                     name = name.replace('/', '_');
1173                 }
1174                 Class<?> invokerClass = new Lookup(targetClass)
1175                         .makeHiddenClassDefiner(name, INJECTED_INVOKER_TEMPLATE)
1176                         .defineClass(true);
1177                 assert checkInjectedInvoker(targetClass, invokerClass);
1178                 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1179             } catch (ReflectiveOperationException ex) {
1180                 throw uncaughtException(ex);
1181             }
1182         }
1183 
1184         private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1185             @Override protected MethodHandle computeValue(Class<?> hostClass) {
1186                 return makeInjectedInvoker(hostClass);
1187             }
1188         };
1189 
1190         // Adapt mh so that it can be called directly from an injected invoker:
1191         private static MethodHandle prepareForInvoker(MethodHandle mh) {
1192             mh = mh.asFixedArity();
1193             MethodType mt = mh.type();
1194             int arity = mt.parameterCount();
1195             MethodHandle vamh = mh.asType(mt.generic());
1196             vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
1197             vamh = vamh.asSpreader(Object[].class, arity);


1253         }
1254 
1255         private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate();
1256 
1257         /** Produces byte code for a class that is used as an injected invoker. */
1258         private static byte[] generateInvokerTemplate() {
1259             ClassWriter cw = new ClassWriter(0);
1260 
1261             // private static class InjectedInvoker {
1262             //     @Hidden
1263             //     static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
1264             //        return vamh.invokeExact(args);
1265             //     }
1266             // }
1267             cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null);
1268 
1269             MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V",
1270                           "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;",
1271                           null, null);
1272 




1273             mv.visitCode();
1274             mv.visitVarInsn(ALOAD, 0);
1275             mv.visitVarInsn(ALOAD, 1);
1276             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact",
1277                                "([Ljava/lang/Object;)Ljava/lang/Object;", false);
1278             mv.visitInsn(ARETURN);
1279             mv.visitMaxs(2, 2);
1280             mv.visitEnd();
1281 
1282             cw.visitEnd();
1283             return cw.toByteArray();
1284         }
1285     }
1286 
1287     /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
1288     private static final class WrappedMember extends DelegatingMethodHandle {
1289         private final MethodHandle target;
1290         private final MemberName member;
1291         private final Class<?> callerClass;
1292         private final boolean isInvokeSpecial;


< prev index next >