private static MethodHandle throwException(Supplier<Throwable> supplier, MethodType type) throws Exception { MethodHandle makeExn = PRIVATE_LOOKUP.findVirtual(Supplier.class, "get", methodType(Object.class)); makeExn = makeExn.bindTo(supplier); makeExn = makeExn.asType(methodType(Throwable.class)); MethodHandle throwExn = MethodHandles.throwException(type.returnType(), Throwable.class); throwExn = MethodHandles.foldArguments(throwExn, makeExn); // discard arguments specified by the provided type return MethodHandles.dropArguments(throwExn, 0, type.parameterArray()); } }
public MethodHandle target() throws Exception { return builder .permute(1, 2) .convert(Object.class, ExecutionContext.class, Object.class) .fold(lookup().findStatic(PrimitiveCallLink.class, "typeError", MethodType.methodType(ThrowException.class, ExecutionContext.class, Object.class))) .drop(1, 2) .invoke(MethodHandles.throwException(Object.class, ThrowException.class)) .target(); }
private static MethodHandle catchExceptions(MethodHandle handle, Converter converter) { MethodHandle thrower = MethodHandles.throwException(handle.type().returnType(), ScriptException.class); thrower = MethodHandles.filterArguments(thrower, 0, converter.toScriptException()); return MethodHandles.catchException(handle, Exception.class, thrower); }
/** * Throw the current signature's sole Throwable argument. Return type * does not matter, since it will never return. * * @return a handle that has all transforms applied and which will eventually throw an exception */ public MethodHandle throwException() { if (type().parameterCount() != 1 || !Throwable.class.isAssignableFrom(type().parameterType(0))) { throw new InvalidTransformException("incoming signature must have one Throwable type as its sole argument: " + type()); } return invoke(MethodHandles.throwException(type().returnType(), type().parameterType(0).asSubclass(Throwable.class))); }