我怎样才能获得通过的所有声明的方法MethodHandles.lookup()
我怎样才能获得的所有声明的字段?
有什么区别betweeen MethodHandle.invoke()
MethodHandle.invokeExact()
和MethodHandle.invokeWithArguments()
另外,我将感激关于使用MethodHandle API的Java devloper教程。 我要强调,我编程的静态类型语言,普通的旧式Java和我不是JVM开发者,尤其是我没有用全字节码废话(invokedynamic)有趣。 我想弄清楚如何我可以用它代替Java核心API这个新的API。
EDITED-2:
@Glen最佳下面提供一些参考文献的我想只提供一个http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50这正是我一直在寻找。 我想通了,其实有一些新的vocabalry。例如,通过目标实际上意味着MethodHandle(而不是反对让发货后),并调用点实际上是代码“所调用”,“函数指针”又名MethodHandle。 此外,它是一定要了解MethodHandle API 不更换核心映像API,而不是suplement它。 举例来说,你不能“发现”与MethodHandle所有的方法,你需要核心映像API。 但是,当你“发现”你需要的方法,你可以切换到MethodHandle和例如,结合它的一些参数或“改变”(适应),它的签名可变参数,例如。
编辑:
我仍然在试图找出答案。 我写了一些测试,我想与大家分享。
package alexander.berkovich;
import static org.junit.Assert.assertSame;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.BeforeClass;
import org.junit.Test;
public class MethodHandlerCleanTest {
public static MethodHandles.Lookup lookup;
@BeforeClass
public static void asetUp(){
lookup = MethodHandles.lookup();
}
public static class Check {
public void primitive(final int i){
}
public void wrapper(final Integer i){
}
}
@Test
public void testPrimitive() throws Throwable {
Check check = new Check();
MethodType type = MethodType.methodType(void.class, int.class);
MethodHandle mh = lookup.findVirtual(Check.class, "primitive", type);
mh.invokeWithArguments(check, 1);
mh.invoke(check, (short)2);
mh.invoke(check, Integer.valueOf(3));
Method method = Check.class.getMethod("primitive", int.class);
method.invoke(check, (short)20);
method.invoke(check, Integer.valueOf(21));
}
@Test
public void testWrapper() throws Throwable {
Check check = new Check();
MethodType type = MethodType.methodType(void.class, Integer.class);
MethodHandle mh = lookup.findVirtual(Check.class, "wrapper", type);
mh.invoke(check, 2);
Method method = Check.class.getMethod("wrapper", Integer.class);
method.invoke(check, 20);
}
@SuppressWarnings("unused")
public static class StaticInnerClass {
public static String staticName;
public String name;
public void foo(){}
public static void staticFoo(){}
}
@Test
public void testStaticInnerClassStaticField() throws Throwable {
MethodHandle mhSet = lookup.findStaticSetter(StaticInnerClass.class, "staticName", String.class);
String expected = "mama";
mhSet.invoke(expected);
MethodHandle mhGet = lookup.findStaticGetter(StaticInnerClass.class, "staticName", String.class);
Object obj = mhGet.invoke();
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testStaticInnerClassField() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
Field f = StaticInnerClass.class.getDeclaredField("name");
MethodHandle mhSetUnreflect = lookup.unreflectSetter(f);
String expectedUnreflect = "unreflect";
mhSetUnreflect.invoke(sut, expectedUnreflect);
MethodHandle mhSet = lookup.findSetter(StaticInnerClass.class, "name", String.class);
String expected = "mama";
mhSet.invoke(sut, expected);
MethodHandle mhGet = lookup.findGetter(StaticInnerClass.class, "name", String.class);
Object obj = mhGet.invoke(sut);
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testStaticInnerClassConstructor() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findConstructor(StaticInnerClass.class, type);
mh.invoke();
}
@Test
public void testStaticInnerClassMethod() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findVirtual(StaticInnerClass.class, "foo", type);
mh.invoke(sut);
}
@Test
public void testStaticInnerClassStaticMethod() throws Throwable {
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findStatic(StaticInnerClass.class, "staticFoo", type);
mh.invoke();
}
@SuppressWarnings("unused")
private class InnerClass {
public String name;
public void foo(){}
}
@Test
public void testInnerClassField() throws Throwable {
InnerClass sut = new InnerClass();
MethodHandle mhSet = lookup.findSetter(InnerClass.class, "name", String.class);
String expected = "mama";
mhSet.invoke(sut, expected);
MethodHandle mhGet = lookup.findGetter(InnerClass.class, "name", String.class);
Object obj = mhGet.invoke(sut);
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testInnerClassConstructor() throws Throwable {
MethodType type = MethodType.methodType(void.class, MethodHandlerCleanTest.class);
//default constructor is private
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
MethodHandles.Lookup trustedLookup = (MethodHandles.Lookup)
field
.get(null);
MethodHandle mh = trustedLookup.findConstructor(InnerClass.class, type);
mh.invoke(this);
}
@Test
public void testInnerClassMethod() throws Throwable {
InnerClass sut = new InnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findVirtual(InnerClass.class, "foo", type);
mh.invoke(sut);
}
}
我怎样才能获得通过MethodHandles.lookup()的所有声明的方法? 我怎样才能获得的所有声明的字段?
认为java.lang.invoke作为(快速表演)扩展到反射(java.lang.reflect中)的 - 即,“调用”类是依赖于“反射”类。
你获得通过反射参考的所有方法/构造/字段(java.lang.Class中和java.lang.reflect中):
java.lang.Class<?> someClass = ...; // obtain a Class somehow // Returns all constructors/methods/fields declared in class, // whether public/protected/package/private, // but does NOT include definitions from any ancestors: java.lang.reflect.Constructor<?>[] declaredConstructors = someClass.getDeclaredConstructors(); java.lang.reflect.Method[] declaredMethods = someClass.getDeclaredMethods(); java.lang.reflect.Field[] declaredFields = someClass.getDeclaredFields(); // Returns all constructors/methods/fields declared as public members // in the class AND all ancestors: java.lang.reflect.Constructor<?>[] publicInheritedConstructors = someClass.getConstructors(); java.lang.reflect.Method[] publicInheritedMethods = someClass.getMethods(); java.lang.reflect.Field[] publicInheritedFields = someClass.getFields();
你可以通过java.lang.invoke.MethodHandles.Lookup它们转换为MethodHandles:
java.lang.invoke.MethodType mt; java.lang.invoke.MethodHandle mh; java.lang.invoke.MethodHandles.Lookup lookup = MethodHandles.lookup(); // process methods for (java.lang.reflect.Method method: declaredMethods) { mh = lookup.unreflect(method); // can call mh.invokeExact (requiring first parameter to be the class' // object instance upon which the method will be invoked, followed by // the methodparameter types, with an exact match parameter and return // types) or // mh.invoke/invokeWithArguments (requiring first parameter to be the // class' object instance upon which the method will be invoked, // followed by the method parameter types, with compatible conversions // performed on input/output types) } // process constructors for (java.lang.reflect.Constructor<?> constructor: declaredConstructors) { mh = lookup.unreflectConstructor(constructor); // can call mh.invokeExact or // mh.invoke/invokeWithArguments } // process field setters for (java.lang.reflect.Field field: declaredFields) { mh = lookup.unreflectSetter(field); // can call mh.invokeExact or // mh.invoke/invokeWithArguments } // process field getters for (java.lang.reflect.Field field: declaredFields) { mh = lookup.unreflectGetter(field); // can call mh.invokeExact or // mh.invoke/invokeWithArguments }
如果通过java.lang.reflect中的方法/构造函数/场的签名就可以判断:
// If generics involved in method signature: Type[] paramTypes = method.getGenericParameterTypes(); Type returnType = method.getGenericReturnType(); // Note: if Class is non-static inner class, first parameter of // getGenericParameterTypes() is the enclosing class // If no generics involved in method signature: Class<?>[] paramTypes = declaredMethod.getParameterTypes(); Class<?> returnType = declaredMethod.getReturnType(); // Note: if Class is non-static inner class, first parameter of // getParameterTypes() is the enclosing class // Same method calls for declaredConstructor
您可以确定方法/构造函数/场通过java.lang.reflect中是静态的:
int modifiers = method.getModifiers(); // same method for constructor/field boolean isStatic = java.lang.Modifier.isStatic(modifiers);
有什么区别betweeen MethodHandle.invoke(),MethodHandle.invokeExact()和MethodHandle.invokeWithArguments()?
- 看到http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html#invoke%28java.lang.Object...%29
- 如果
MethodHandle
为非静态方法中,提供给这些方法的第一个参数是一个实例Class
,其声明了方法。 该方法被调用的类(或类本身为静态方法)的此实例。 如果Class
是一个非静态内部类,第二个参数是封闭的/声明类的一个实例。 随后的参数是方法签名参数,为了。 -
invokeExact
不做输入参数自动兼容的类型转换。 它需要的参数值(或参数表达式)是一个精确的类型匹配方法签名,以作为单独的参数提供的每个参数或一起设置成阵列的所有参数(签名: Object invokeExact(Object... args)
)。 -
invoke
需要的参数值(或参数表达式)是类型兼容匹配方法签名-自动类型转换被执行,以作为单独的参数提供的每个参数或一起设置成阵列(签名的所有参数:对象调用(对象。 ..参数)) -
invokeWithArguments
需要的参数值(或参数表达式)是类型兼容匹配方法签名-自动类型转换被执行,以列表内提供的每个参数(签名: Object invokeWithArguments(List<?> arguments)
)
我会感激教程的有关使用MethodHandle API的Java devloper
有没有什么在那里,很可惜。 你可以尝试以下。 但愿,我已经给了足够的信息上面:^)
http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html
http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandles.Lookup.html
http://www.java7developer.com/blog/?p=191
http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50
http://www.amazon.com/Well-Grounded-Java-Developer-techniques-programming/dp/1617290068
有什么区别betweeen MethodHandle.invoke(),MethodHandle.invokeExact()和MethodHandle.invokeWithArguments()
因为我也有这个挣扎,我决定重新审视这个问题,并写,准确显示这些方法之间的语义差别就是一个例子。
其主要差异如下:
invokeExact
只接受精确的参数和返回值,并且不接受参数数组。 调用如方法签名(Integer,Integer)Integer
与int
参数是不允许的,但也有称其为Object
的说法是不允许的,即使对象实际上是整数类型-参数的编译时类型必须是一流的整数,而不是运行时实例:
Object arg = 1; Object[] args = {1,1}; Integer i = (Integer)handle.invokeExact(1,1); // OK Object o = handle.invokeExact(arg,arg); // ERROR handle.invokeExact(args); // ERROR
invoke
自动转换参数类型和返回类型,并且还变换原始类型和相应的包装类之间。 但这也不能接受参数数组。 例如用于方法签名(Integer,Integer)Integer
:
Object arg = 1; Object[] args = {1,1}; Integer i = (Integer)handle.invoke(1,1); // OK Object o = handle.invoke(arg,arg); // OK! o = handle.invoke(args); // ERROR
invokeWithArguments
删除所有这些限制,而且运作非常相似的Method#invoke
-你也可以提供一个阵列(或java.util.List
)作为参数(但是这种灵活性是一个巨大的性能损失)。 例如用于方法签名(Integer,Integer)Integer
:
Object arg = 1; Object[] args = {1,1}; Integer i = (Integer)handle.invokeWithArguments(1,1); // OK Object o = handle.invokeWithArguments(arg,arg); // OK o = handle.invokeWithArguments(args); // OK!
这里一个完整的例子:
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class MethodHandleTest {
public static class TestClass{
public int test(int a, Integer b){
return a+b;
}
}
public static void main(String[] args) throws Throwable{
Method method = TestClass.class.getMethod("test", int.class, Integer.class);
MethodHandle handle = MethodHandles.lookup().unreflect(method).bindTo(new TestClass());
int arg_int = 1;
Integer argInteger = 1;
Object[] argArray = {1,1};
//----------------------------
// MethodHandle#invokeExact()
//----------------------------
// ONLY an exact invocation is allowed for invokeExact:
int result = (int) handle.invokeExact(arg_int, argInteger);
// inexact first argument type -> throws WrongMethodTypeException - "expected (int,Integer)int but found (Integer,Integer)int"
Exception e = null;
try {
result = (int) handle.invokeExact(argInteger,argInteger);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
// inexact return type -> throws WrongMethodTypeException - "expected (int,Integer)int but found (int,Integer)Integer"
try {
result = (Integer) handle.invokeExact(arg_int,argInteger);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
// inexact return type -> throws WrongMethodTypeException - "expected (int,Integer)int but found (int,Integer)Object"
try {
Object o = handle.invokeExact(arg_int,argInteger);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
// "argObject" is ALSO NOT OK! - the compile time type of the argument must be of class Integer, not the runtime instance!
// -> throws WrongMethodTypeException - "expected (int,Integer)int but found (int,Object)int"
Object argObject = argInteger;
try {
result = (int) handle.invokeExact(arg_int,argObject);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
// Array of the arguments NOT allowed -> throws WrongMethodTypeException - "expected (int,Integer)int but found (Object[])int"
try {
result = (int) handle.invokeExact(argArray);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
// But explicit cast of first or second argument is OK
result = (int) handle.invokeExact((int)argInteger,argInteger);
result = (int) handle.invokeExact(arg_int,(Integer)arg_int);
//-----------------------
// MethodHandle#invoke()
//-----------------------
// invoke() with exact types - OK -> actually calls invokeExact() behind the scenes
result = (int) handle.invoke(arg_int, argInteger);
// implicit conversion of inexact arguments and return type -> OK!
result = (Integer) handle.invoke(argInteger,argInteger);
// Object arguments or return type is OK!
Object o = handle.invoke(argObject,argObject);
// Array of the arguments NOT allowed -> throws WrongMethodTypeException - "cannot convert MethodHandle(int,Integer)int to (Object[])int"
try {
result = (int) handle.invoke(argArray);
} catch (WrongMethodTypeException ex) {
e = ex;
}
assert e != null;
e = null;
//------------------------------------
// MethodHandle#invokeWithArguments()
//------------------------------------
// invoke() with exact types - OK
result = (int) handle.invokeWithArguments(arg_int,arg_int);
// implicit conversion of inexact arguments and return type -> OK
result = (Integer) handle.invokeWithArguments(argInteger,argInteger);
// Object arguments or return type is OK!
o = handle.invoke(argObject,argObject);
// Array of the arguments -> OK
result = (int) handle.invokeWithArguments(argArray);
// List of arguments possible -> same as calling invokeWithArguments(list.toArray())
result = (int) handle.invokeWithArguments(Arrays.asList(argArray));
}
}
由于巴尔德说,两个呼叫invoke
和invokeExact
不接受传递作为数组变量。 (不过,他们确实接受数组参数。)
int[] args = {1,1};
// handle for Math.addExact(int, int)
Object o = handle.invokeExact(1,1); // OK
Object o = handle.invoke(1,1); // OK
Object o = handle.invokeExact(args); // ERROR
Object o = handle.invoke(args); // ERROR
该错误是总是一个错误类型的异常:
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(int, int)int to (Object[])int
所以它不解压阵列。 但通过在其要求的作品的数组:
// handle for Arrays.sort(int[])
handle.invokeExact(args); // OK
handle.invoke(args); // OK
由于巴尔德说,实现与期望的行为invokeWithArguments()
可能会产生相当大的开销。
为了得到所期望的行为从可变参数称为拆包参数列表,就必须转动手柄到吊具:
// handle for Math.addExact(int, int)
handle = handle.asSpreader(int[].class, 2);
handle.invokeExact(args); // OK
handle.invoke(args); // OK
当然,相同的功能,用于当再次阵列被定义为通用显式的参数传递帐户:
Object[] args = new Object[]{1,1};
// handle for Math.addExact(int, int)
handle = handle.asSpreader(int[].class, 2);
handle.invokeExact(args); // ERROR
handle.invoke(args); // OK
我没有进行呼叫之间的任何性能对比。 对于那些有兴趣,这是很简单的扩展这个基准: http://rick-hightower.blogspot.de/2013/10/java-invoke-dynamic-examples-java-7.html
细节:
从本质上讲invokeWithArguments
做类似的事情,但这样做的每一个电话:
public Object invokeWithArguments(Object... arguments) throws Throwable {
MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length);
return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments);
}
因此,创建一个吊具一次,重新使用,将最有可能收益表现为类似的invoke
和invokeExact
。