下面列出了java.lang.invoke.MethodType#methodType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private MethodHandle getMethodHandle(StdUDF stdUDF, Metadata metadata, BoundVariables boundVariables,
boolean[] nullableArguments, AtomicLong requiredFilesNextRefreshTime) {
Type[] inputTypes = getPrestoTypes(stdUDF.getInputParameterSignatures(), metadata, boundVariables);
Type outputType = getPrestoType(stdUDF.getOutputParameterSignature(), metadata, boundVariables);
// Generic MethodHandle for eval where all arguments are of type Object
Class<?>[] genericMethodHandleArgumentTypes = getMethodHandleArgumentTypes(inputTypes, nullableArguments, true);
MethodHandle genericMethodHandle =
methodHandle(StdUdfWrapper.class, "evalInternal", genericMethodHandleArgumentTypes).bindTo(this);
Class<?>[] specificMethodHandleArgumentTypes = getMethodHandleArgumentTypes(inputTypes, nullableArguments, false);
Class<?> specificMethodHandleReturnType = getJavaTypeForNullability(outputType, true);
MethodType specificMethodType =
MethodType.methodType(specificMethodHandleReturnType, specificMethodHandleArgumentTypes);
// Specific MethodHandle required by presto where argument types map to the type signature
MethodHandle specificMethodHandle = MethodHandles.explicitCastArguments(genericMethodHandle, specificMethodType);
return MethodHandles.insertArguments(specificMethodHandle, 0, stdUDF, inputTypes,
outputType instanceof IntegerType, requiredFilesNextRefreshTime);
}
@Test(dataProvider = "versions")
public void test(String version, int expected) throws Throwable {
StandardJavaFileManager jfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
jfm.setLocation(jloc, List.of(new File("multi-release.jar")));
if (version.length() > 0) {
jfm.handleOption("--multi-release", List.of(version).iterator());
}
CustomClassLoader cldr = new CustomClassLoader(jfm);
Class<?> versionClass = cldr.loadClass("version.Version");
MethodType mt = MethodType.methodType(int.class);
MethodHandle mh = MethodHandles.lookup().findVirtual(versionClass, "getVersion", mt);
int v = (int)mh.invoke(versionClass.newInstance());
Assert.assertEquals(v, expected);
jfm.close();
}
private static void test(String pkg) throws Throwable {
byte[] bytes = dumpClass(pkg);
// Define VM anonymous class in privileged context (on BCP).
Class anonClass = unsafe.defineAnonymousClass(Object.class, bytes, null);
MethodType t = MethodType.methodType(Object.class, int.class);
MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);
// Wrap target into LF (convert) to get "target" referenced from LF
MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));
// Invoke enough times to provoke LF compilation to bytecode.
for (int i = 0; i<100; i++) {
Object r = wrappedMH.invokeExact((Integer)1);
}
}
/**
* Routine used to obtain a randomly generated method type.
*
* @param arity Arity of returned method type.
* @return MethodType generated randomly.
*/
public static MethodType randomMethodTypeGenerator(int arity) {
final Class<?>[] CLASSES = {
Object.class,
int.class,
boolean.class,
byte.class,
short.class,
char.class,
long.class,
float.class,
double.class
};
if (arity > MAX_ARITY) {
throw new IllegalArgumentException(
String.format("Arity should not exceed %d!", MAX_ARITY));
}
List<Class<?>> list = randomClasses(CLASSES, arity);
list = getParams(list, false, arity);
int i = RNG.nextInt(CLASSES.length + 1);
Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
return MethodType.methodType(rtype, list);
}
static MethodHandle MH_hashArguments(Class<? extends Object[]> arrayClass, int arity) {
if (arrayClass == Object[].class)
return MH_hashArguments(arity);
ArrayList<Class<?>> ptypes = new ArrayList<>(Collections.<Class<?>>nCopies(arity, arrayClass.getComponentType()));
MethodType mt = MethodType.methodType(Object.class, ptypes);
return MH_hashArguments_VA.asType(mt);
}
static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable {
if (dst == Wrapper.OBJECT || src == Wrapper.OBJECT) return; // must have prims
if (dst == Wrapper.VOID || src == Wrapper.VOID ) return; // must have values
boolean testSingleCase = (tval != 0);
final long tvalInit = tval;
MethodHandle conv = ValueConversions.convertPrimitive(src, dst);
MethodType convType = MethodType.methodType(dst.primitiveType(), src.primitiveType());
assertEquals(convType, conv.type());
MethodHandle converter = conv.asType(conv.type().changeReturnType(Object.class));
for (;;) {
long n = tval;
Object testValue = src.wrap(n);
Object expResult = dst.cast(testValue, dst.primitiveType());
Object result;
switch (src) {
case INT: result = converter.invokeExact((int)n); break;
case LONG: result = converter.invokeExact(/*long*/n); break;
case FLOAT: result = converter.invokeExact((float)n); break;
case DOUBLE: result = converter.invokeExact((double)n); break;
case CHAR: result = converter.invokeExact((char)n); break;
case BYTE: result = converter.invokeExact((byte)n); break;
case SHORT: result = converter.invokeExact((short)n); break;
case BOOLEAN: result = converter.invokeExact((n & 1) != 0); break;
default: throw new AssertionError();
}
assertEquals("(src,dst,n,testValue)="+Arrays.asList(src,dst,"0x"+Long.toHexString(n),testValue),
expResult, result);
if (testSingleCase) break;
// next test value:
tval = nextTestValue(tval);
if (tval == tvalInit) break; // repeat
}
}
/**
* Test of make method, of class MethodType.
*/
@Test
public void testMake_Class_ClassArr() {
System.out.println("make (from type array)");
MethodType result = MethodType.methodType(rtype, ptypes);
assertSame(mt_viS, result);
}
static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable {
//System.out.println(src+" => "+dst);
boolean testSingleCase = (tval != 0);
final long tvalInit = tval;
MethodHandle conv = ValueConversions.convertPrimitive(src, dst);
MethodType convType;
if (src == Wrapper.VOID)
convType = MethodType.methodType(dst.primitiveType() /* , void */);
else
convType = MethodType.methodType(dst.primitiveType(), src.primitiveType());
assertEquals(convType, conv.type());
MethodHandle converter = conv.asType(conv.type().changeReturnType(Object.class));
for (;;) {
long n = tval;
Object testValue = src.wrap(n);
Object expResult = dst.cast(testValue, dst.primitiveType());
Object result;
switch (src) {
case INT: result = converter.invokeExact((int)n); break;
case LONG: result = converter.invokeExact(/*long*/n); break;
case FLOAT: result = converter.invokeExact((float)n); break;
case DOUBLE: result = converter.invokeExact((double)n); break;
case CHAR: result = converter.invokeExact((char)n); break;
case BYTE: result = converter.invokeExact((byte)n); break;
case SHORT: result = converter.invokeExact((short)n); break;
case OBJECT: result = converter.invokeExact((Object)n); break;
case BOOLEAN: result = converter.invokeExact((n & 1) != 0); break;
case VOID: result = converter.invokeExact(); break;
default: throw new AssertionError();
}
assertEquals("(src,dst,n,testValue)="+Arrays.asList(src,dst,"0x"+Long.toHexString(n),testValue),
expResult, result);
if (testSingleCase) break;
// next test value:
tval = nextTestValue(tval);
if (tval == tvalInit) break; // repeat
}
}
/**
* Test of make method, of class MethodType.
*/
@Test
public void testMake_3args() {
System.out.println("make (from type with varargs)");
MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
assertSame(mt_viS, result);
}
public GraphListener() {
boolean mainHandMethodEx = false;
try {
MethodType type = MethodType.methodType(ItemStack.class);
MethodHandles.publicLookup().findVirtual(PlayerInventory.class, "getItemInMainHand", type);
mainHandMethodEx = true;
} catch (ReflectiveOperationException notFoundEx) {
//default to false
}
this.mainHandSupported = mainHandMethodEx;
}
public static void main(String[] args) throws Throwable {
MethodHandle mh = MethodHandles.lookup().findVirtual(CharSequence.class, "toString", MethodType.methodType(String.class));
MethodType mt = MethodType.methodType(Object.class, CharSequence.class);
mh = mh.asType(mt);
Object res = mh.invokeExact((CharSequence)"123");
System.out.println("TEST PASSED");
}
/**
* Test of make method, of class MethodType.
*/
@Test
public void testMake_Class_List() {
System.out.println("make (from type list)");
MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
assertSame(mt_viS, result);
}
/**
* Test of make method, of class MethodType.
*/
@Test
public void testMake_Class_List() {
System.out.println("make (from type list)");
MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
assertSame(mt_viS, result);
}
private static MethodType getMethodType(final AccessibleObject ao) {
final boolean isMethod = ao instanceof Method;
final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass();
final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes();
final MethodType type = MethodType.methodType(rtype, ptypes);
final Member m = (Member)ao;
return type.insertParameterTypes(0,
isMethod ?
Modifier.isStatic(m.getModifiers()) ?
Object.class :
m.getDeclaringClass() :
StaticClass.class);
}
public void level(Object logger, String msg, ResourceBundle bundle,
Object... params) {
MethodType mt = MethodType.methodType(void.class, Level.class,
ResourceBundle.class, String.class, Object[].class);
invoke("logrb", logger, mt, platformLevel, bundle, msg, params);
}
@Test
@Tag("PASSING")
@Order(2)
public void methodHandleParamConstructor() {
String expectedOutput = "[Constructor Demo] - Constructor via Method Handles";
/*
* DONE:
* The API provides a few lookup mechanisms. For a public constructor, on a
* public class, we can use the lookup with minimal checks and trust.
* Public members of public classes are looked up via "public lookups"
* Check API: java.lang.invoke.MethodHandles.publicLookup()
*/
MethodHandles.Lookup publicMethodHandlesLookup = MethodHandles.publicLookup();
/*
* DONE:
* Create a methodType instance that matches the constructor that takes a string param
* Constructors should have a void return type
* This constructor has a string parameter
* Search for method that: has a return type of void (Constructor)
* and accepts a String parameter.
* Check API: java.lang.invoke.MethodType.methodType(?, ?)
*/
MethodType methodType = MethodType.methodType(void.class, String.class);
try {
/*
* DONE:
* Replace the "nulls" to find a constructor handle for DemoClass using methodType
* "Find" a constructor of the class via the Lookup instance,
* based on the methodType described above
* Check API: java.lang.invoke.MethodHandles.Lookup.findConstructor(?, ?)
*/
MethodHandle demoClassConstructor =
publicMethodHandlesLookup.findConstructor(DemoClass.class, methodType);
// Hint: Class and MethodType
/*
* DONE:
* Invoke the constructor and pass in "Constructor Demo" as the parameter.
* Create an instance of the DemoClass by invoking the method handle
* The MethodHandle has two methods invoke() and invokeExact()
* The invoke() is good for conversion/substitution of param types
* The invokeExact() is great if there is no ambiguity
* Check API: java.lang.invoke.MethodHandle.invokeExact(?)
*/
DemoClass demoClass =
(DemoClass) demoClassConstructor.invokeExact(
"Constructor Demo");
assertEquals(expectedOutput,
demoClass.printStuff(
"Constructor via Method Handles"),
"Method handles invocation failed");
} catch (NoSuchMethodException | IllegalAccessException e) {
fail("Failed to execute a constructor invocation via Method Handles: "
+ e.getMessage());
} catch (Throwable t) {
// invokeExact() throws a Throwable (hence catching Throwable separately).
fail(TEST_FAILURE.getValue() + t.getMessage());
}
}
/**
* Creates and returns a new MutableCallSite,
// * recording it in list of all callsites for this type, in a map by typename
// *
// * Done this way because
// * - can't be a classloader-wide list of call sites - some might not be associated with this type system
// * - can't be a typesystem-wide list of call sites - the JCas class might be used by multiple type systems
// * and the first one to load it would set this value.
// * - has to be pairs of feature name, call-site, in order to get the value to set, later
// * -- doesn't need to be a hashmap, can be an arraylist of entry
// * Type being loaded may not be known at this point.
* @param clazz the JCas class
* @param featName the short name of the feature
* @return the created callsite
*/
public final static MutableCallSite createCallSite(Class<? extends TOP> clazz, String featName) {
MutableCallSite callSite = new MutableCallSite(MethodType.methodType(int.class));
callSite.setTarget(MHC_MINUS_1); // for error checking
// ArrayList<Entry<String, MutableCallSite>> callSitesForType = FSClassRegistry.callSites_all_JCasClasses.computeIfAbsent(clazz, k -> new ArrayList<>());
// callSitesForType.add(new AbstractMap.SimpleEntry<String, MutableCallSite>(featName, callSite));
return callSite;
}
private static MethodType mt(Class<?> k, Class<?> k2) { return MethodType.methodType(k, k2); }
private static MethodType mt(Class<?> k) { return MethodType.methodType(k); }
private static MethodType mt(Class<?> k) { return MethodType.methodType(k); }