下面列出了java.lang.invoke.MethodHandles#explicitCastArguments ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* setting a call site target consists of the following steps:
* # get the meta class
* # select a method/constructor/property from it, if it is a MetaClassImpl
* # make a handle out of the selection
* # if nothing could be selected select a path through the given MetaClass or the GroovyObject
* # apply transformations for vargs, implicit null argument, coercion, wrapping, null receiver and spreading
*/
@Override
public void setCallSiteTarget() {
if (!setNullForSafeNavigation() && !setInterceptor()) {
getMetaClass();
if (LOG_ENABLED) LOG.info("meta class is " + mc);
setSelectionBase();
MetaClassImpl mci = getMetaClassImpl(mc, callType != CallType.GET);
chooseMeta(mci);
setHandleForMetaMethod();
setMetaClassCallHandleIfNeeded(mci != null);
correctParameterLength();
correctCoerce();
correctWrapping();
correctNullReceiver();
correctSpreading();
if (LOG_ENABLED) LOG.info("casting explicit from " + handle.type() + " to " + targetType);
handle = MethodHandles.explicitCastArguments(handle, targetType);
addExceptionHandler();
}
setGuards(args[0]);
doCallSiteTargetSet();
}
private static MethodHandle buildSetter(Class<?> arrayClass) {
MethodHandle set = MethodHandles.arrayElementSetter(arrayClass);
MethodHandle fallback = MethodHandles.explicitCastArguments(set, set.type().changeParameterType(0, Object.class));
fallback = MethodHandles.dropArguments(fallback, 3, int.class);
MethodType reorderType = fallback.type().
insertParameterTypes(0, int.class).
dropParameterTypes(4, 5);
fallback = MethodHandles.permuteArguments(fallback, reorderType, 1, 0, 3, 0);
fallback = MethodHandles.foldArguments(fallback, normalizeIndex);
fallback = MethodHandles.explicitCastArguments(fallback, set.type());
MethodHandle guard = MethodHandles.dropArguments(notNegative, 0, arrayClass);
MethodHandle handle = MethodHandles.guardWithTest(guard, set, fallback);
return handle;
}
public static MethodHandle zeroConstantFunction(Wrapper wrap) {
WrapperCache cache = CONSTANT_FUNCTIONS[0];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
return mh;
}
// slow path
MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) {
case VOID:
mh = EMPTY;
break;
case OBJECT:
case INT: case LONG: case FLOAT: case DOUBLE:
try {
mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
} catch (ReflectiveOperationException ex) {
mh = null;
}
break;
}
if (mh != null) {
return cache.put(wrap, mh);
}
// use zeroInt and cast the result
if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
return cache.put(wrap, mh);
}
throw new IllegalArgumentException("cannot find zero constant for " + wrap);
}
public static MethodHandle zeroConstantFunction(Wrapper wrap) {
WrapperCache cache = CONSTANT_FUNCTIONS[0];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
return mh;
}
// slow path
MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) {
case VOID:
mh = EMPTY;
break;
case OBJECT:
case INT: case LONG: case FLOAT: case DOUBLE:
try {
mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
} catch (ReflectiveOperationException ex) {
mh = null;
}
break;
}
if (mh != null) {
return cache.put(wrap, mh);
}
// use zeroInt and cast the result
if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
return cache.put(wrap, mh);
}
throw new IllegalArgumentException("cannot find zero constant for " + wrap);
}
private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {
try {
MethodHandles.explicitCastArguments(mh, mt);
throw new AssertionError("Expected WrongMethodTypeException is not thrown");
} catch (WrongMethodTypeException wmte) {
if (VERBOSE) {
System.out.printf("Expected exception %s: %s\n",
wmte.getClass(), wmte.getMessage());
}
}
}
public static MethodHandle arraySet(MethodType type) {
Class<?> key = type.parameterType(0);
MethodHandle res = setterMap.get(key);
if (res != null) return res;
res = buildSetter(key);
res = MethodHandles.explicitCastArguments(res, type);
return res;
}
/**
* Tests that MHs.explicitCastArguments does incorrect type checks for
* VarargsCollector. Bug 8066746.
*
* @throws java.lang.Throwable
*/
public static void testVarargsCollector() throws Throwable {
MethodType mt = MethodType.methodType(String[].class, String[].class);
MethodHandle mh = MethodHandles.publicLookup()
.findStatic(THIS_CLASS, "f", mt);
mh = MethodHandles.explicitCastArguments(mh,
MethodType.methodType(Object.class, Object.class));
mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));
}
private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {
try {
MethodHandles.explicitCastArguments(mh, mt);
throw new AssertionError("Expected WrongMethodTypeException is not thrown");
} catch (WrongMethodTypeException wmte) {
if (VERBOSE) {
System.out.printf("Expected exception %s: %s\n",
wmte.getClass(), wmte.getMessage());
}
}
}
public static MethodHandle zeroConstantFunction(Wrapper wrap) {
EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
return mh;
}
// slow path
MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) {
case VOID:
mh = EMPTY;
break;
case OBJECT:
case INT: case LONG: case FLOAT: case DOUBLE:
try {
mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
} catch (ReflectiveOperationException ex) {
mh = null;
}
break;
}
if (mh != null) {
cache.put(wrap, mh);
return mh;
}
// use zeroInt and cast the result
if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
cache.put(wrap, mh);
return mh;
}
throw new IllegalArgumentException("cannot find zero constant for " + wrap);
}
static MethodHandle tweak(MethodHandle mh, int argPos, Class<?> type) {
MethodType mt = mh.type();
if (argPos == -1)
mt = mt.changeReturnType(type);
else
mt = mt.changeParameterType(argPos, type);
return MethodHandles.explicitCastArguments(mh, mt);
}
/**
* Tests that MHs.eCA method works correctly with MHs with multiple arguments.
* @throws Throwable
*/
public static void testMultipleArgs() throws Throwable {
int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);
int arityMinus = RNG.nextInt(arity);
int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;
MethodType mType = Helper.randomMethodTypeGenerator(arity);
MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);
MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);
MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);
Class<?> rType = mType.returnType();
MethodHandle original;
if (rType.equals(void.class)) {
MethodType mt = MethodType.methodType(void.class);
original = MethodHandles.publicLookup()
.findStatic(THIS_CLASS, "retVoid", mt);
} else {
Object rValue = Helper.castToWrapper(1, rType);
original = MethodHandles.constant(rType, rValue);
}
original = Helper.addTrailingArgs(original, arity, mType.parameterList());
MethodHandle target = MethodHandles
.explicitCastArguments(original, mTypeNew);
Object[] parList = Helper.randomArgs(mTypeNew.parameterList());
for (int i = 0; i < parList.length; i++) {
if (parList[i] instanceof String) {
parList[i] = null; //getting rid of Stings produced by randomArgs
}
}
target.invokeWithArguments(parList);
checkForWrongMethodTypeException(original, mTypeNewMinus);
checkForWrongMethodTypeException(original, mTypeNewPlus);
}
public static MethodHandle zeroConstantFunction(Wrapper wrap) {
WrapperCache cache = CONSTANT_FUNCTIONS[0];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
return mh;
}
// slow path
MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) {
case VOID:
mh = EMPTY;
break;
case OBJECT:
case INT: case LONG: case FLOAT: case DOUBLE:
try {
mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
} catch (ReflectiveOperationException ex) {
mh = null;
}
break;
}
if (mh != null) {
return cache.put(wrap, mh);
}
// use zeroInt and cast the result
if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
return cache.put(wrap, mh);
}
throw new IllegalArgumentException("cannot find zero constant for " + wrap);
}
/**
* Tests that MHs.explicitCastArguments does incorrect type checks for
* VarargsCollector. Bug 8066746.
*
* @throws java.lang.Throwable
*/
public static void testVarargsCollector() throws Throwable {
MethodType mt = MethodType.methodType(String[].class, String[].class);
MethodHandle mh = MethodHandles.publicLookup()
.findStatic(THIS_CLASS, "f", mt);
mh = MethodHandles.explicitCastArguments(mh,
MethodType.methodType(Object.class, Object.class));
mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));
}
public static MethodHandle zeroConstantFunction(Wrapper wrap) {
WrapperCache cache = CONSTANT_FUNCTIONS[0];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
return mh;
}
// slow path
MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) {
case VOID:
mh = EMPTY;
break;
case OBJECT:
case INT: case LONG: case FLOAT: case DOUBLE:
try {
mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
} catch (ReflectiveOperationException ex) {
mh = null;
}
break;
}
if (mh != null) {
return cache.put(wrap, mh);
}
// use zeroInt and cast the result
if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
return cache.put(wrap, mh);
}
throw new IllegalArgumentException("cannot find zero constant for " + wrap);
}
public static MethodHandle cast(MethodHandle mh, MethodType mt) throws Throwable {
println("calling " + mh.type() + " as " + mt);
if (explicit) {
return MethodHandles.explicitCastArguments(mh, mt);
} else {
return mh.asType(mt);
}
}
public static MethodHandle cast(MethodHandle mh, MethodType mt) throws Throwable {
println("calling " + mh.type() + " as " + mt);
if (explicit) {
return MethodHandles.explicitCastArguments(mh, mt);
} else {
return mh.asType(mt);
}
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
return MethodHandles.explicitCastArguments(target, type);
}
private void castAndSetGuards() {
handle = MethodHandles.explicitCastArguments(handle, targetType);
setGuards(args[0]);
doCallSiteTargetSet();
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
final MethodHandle mh = MethodHandles.explicitCastArguments(target, type);
return debug(mh, "explicitCastArguments", target, type);
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
return MethodHandles.explicitCastArguments(target, type);
}