< prev index next >

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

Print this page




1151         MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1152             // Code in the boot layer should now be careful while creating method handles or
1153             // functional interface instances created from method references to @CallerSensitive  methods,
1154             // it needs to be ensured the handles or interface instances are kept safe and are not passed
1155             // from the boot layer to untrusted code.
1156             if (hostClass == null
1157                 ||    (hostClass.isArray() ||
1158                        hostClass.isPrimitive() ||
1159                        hostClass.getName().startsWith("java.lang.invoke."))) {
1160                 throw new InternalError();  // does not happen, and should not anyway
1161             }
1162             // For simplicity, convert mh to a varargs-like method.
1163             MethodHandle vamh = prepareForInvoker(mh);
1164             // Cache the result of makeInjectedInvoker once per argument class.
1165             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1166             return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1167         }
1168 
1169         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
1170             try {







1171                 Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null);
1172                 assert checkInjectedInvoker(hostClass, invokerClass);
1173                 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1174             } catch (ReflectiveOperationException ex) {
1175                 throw uncaughtException(ex);
1176             }
1177         }
1178 
1179         private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1180             @Override protected MethodHandle computeValue(Class<?> hostClass) {
1181                 return makeInjectedInvoker(hostClass);
1182             }
1183         };
1184 
1185         // Adapt mh so that it can be called directly from an injected invoker:
1186         private static MethodHandle prepareForInvoker(MethodHandle mh) {
1187             mh = mh.asFixedArity();
1188             MethodType mt = mh.type();
1189             int arity = mt.parameterCount();
1190             MethodHandle vamh = mh.asType(mt.generic());


1781             public Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
1782                     final String types) {
1783                 return GenerateJLIClassesHelper
1784                         .generateConcreteBMHClassBytes(types);
1785             }
1786 
1787             @Override
1788             public byte[] generateBasicFormsClassBytes(final String className) {
1789                 return GenerateJLIClassesHelper
1790                         .generateBasicFormsClassBytes(className);
1791             }
1792 
1793             @Override
1794             public byte[] generateInvokersHolderClassBytes(final String className,
1795                     MethodType[] invokerMethodTypes,
1796                     MethodType[] callSiteMethodTypes) {
1797                 return GenerateJLIClassesHelper
1798                         .generateInvokersHolderClassBytes(className,
1799                                 invokerMethodTypes, callSiteMethodTypes);
1800             }
1801 
1802         });
1803     }
1804 
1805     /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
1806     private static MethodHandle unboxResultHandle(Class<?> returnType) {
1807         if (returnType.isPrimitive()) {
1808             if (returnType == void.class) {
1809                 return ValueConversions.ignore();
1810             } else {
1811                 Wrapper w = Wrapper.forPrimitiveType(returnType);
1812                 return ValueConversions.unboxExact(w);
1813             }
1814         } else {
1815             return MethodHandles.identity(Object.class);
1816         }
1817     }
1818 
1819     /**
1820      * Assembles a loop method handle from the given handles and type information.
1821      *




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


1788             public Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
1789                     final String types) {
1790                 return GenerateJLIClassesHelper
1791                         .generateConcreteBMHClassBytes(types);
1792             }
1793 
1794             @Override
1795             public byte[] generateBasicFormsClassBytes(final String className) {
1796                 return GenerateJLIClassesHelper
1797                         .generateBasicFormsClassBytes(className);
1798             }
1799 
1800             @Override
1801             public byte[] generateInvokersHolderClassBytes(final String className,
1802                     MethodType[] invokerMethodTypes,
1803                     MethodType[] callSiteMethodTypes) {
1804                 return GenerateJLIClassesHelper
1805                         .generateInvokersHolderClassBytes(className,
1806                                 invokerMethodTypes, callSiteMethodTypes);
1807             }

1808         });
1809     }
1810 
1811     /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
1812     private static MethodHandle unboxResultHandle(Class<?> returnType) {
1813         if (returnType.isPrimitive()) {
1814             if (returnType == void.class) {
1815                 return ValueConversions.ignore();
1816             } else {
1817                 Wrapper w = Wrapper.forPrimitiveType(returnType);
1818                 return ValueConversions.unboxExact(w);
1819             }
1820         } else {
1821             return MethodHandles.identity(Object.class);
1822         }
1823     }
1824 
1825     /**
1826      * Assembles a loop method handle from the given handles and type information.
1827      *


< prev index next >