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;
|