799 // That way we can lazily load the code and set up the constants. |
799 // That way we can lazily load the code and set up the constants. |
800 private static class BindCaller { |
800 private static class BindCaller { |
801 static |
801 static |
802 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) { |
802 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) { |
803 // Do not use this function to inject calls into system classes. |
803 // Do not use this function to inject calls into system classes. |
804 if (hostClass == null) { |
804 if (hostClass == null |
805 hostClass = C_Trampoline; |
805 || (hostClass.isArray() || |
806 } else if (hostClass.isArray() || |
|
807 hostClass.isPrimitive() || |
806 hostClass.isPrimitive() || |
808 hostClass.getName().startsWith("java.") || |
807 hostClass.getName().startsWith("java.") || |
809 hostClass.getName().startsWith("sun.")) { |
808 hostClass.getName().startsWith("sun."))) { |
810 throw new InternalError(); // does not happen, and should not anyway |
809 throw new InternalError(); // does not happen, and should not anyway |
811 } |
810 } |
812 // For simplicity, convert mh to a varargs-like method. |
811 // For simplicity, convert mh to a varargs-like method. |
813 MethodHandle vamh = prepareForInvoker(mh); |
812 MethodHandle vamh = prepareForInvoker(mh); |
814 // Cache the result of makeInjectedInvoker once per argument class. |
813 // Cache the result of makeInjectedInvoker once per argument class. |
815 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); |
814 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); |
816 return restoreToType(bccInvoker.bindTo(vamh), mh.type()); |
815 return restoreToType(bccInvoker.bindTo(vamh), mh.type()); |
817 } |
|
818 |
|
819 // This class ("Trampoline") is known to be inside a dead-end class loader. |
|
820 // Inject all doubtful calls into this class. |
|
821 private static Class<?> C_Trampoline; |
|
822 static { |
|
823 Class<?> tramp = null; |
|
824 try { |
|
825 final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline |
|
826 java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class); |
|
827 tramp = (Class<?>) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG }); |
|
828 if (tramp.getClassLoader() == BindCaller.class.getClassLoader()) |
|
829 throw new RuntimeException(tramp.getName()+" class loader"); |
|
830 } catch (Throwable ex) { |
|
831 throw new InternalError(ex); |
|
832 } |
|
833 C_Trampoline = tramp; |
|
834 } |
816 } |
835 |
817 |
836 private static MethodHandle makeInjectedInvoker(Class<?> hostClass) { |
818 private static MethodHandle makeInjectedInvoker(Class<?> hostClass) { |
837 Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); |
819 Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); |
838 if (hostClass.getClassLoader() != bcc.getClassLoader()) |
820 if (hostClass.getClassLoader() != bcc.getClassLoader()) |