我正在写一些调用的代码Field.set和Field.get数千次.显然,由于反射,这是非常缓慢的.
我想看看我是否可以MethodHandle在Java7中提高性能.到目前为止,这就是我所拥有的:
而不是field.set(pojo, value),我正在做:
private static final Map<Field, MethodHandle> setHandles = new HashMap<>();
MethodHandle mh = setHandles.get(field);
if (mh == null) {
mh = lookup.unreflectSetter(field);
setHandles.put(field, mh);
}
mh.invoke(pojo, value);
Run Code Online (Sandbox Code Playgroud)
但是,这似乎没有比使用反射的Field.set调用更好.我在这里做错了吗?
我读到使用invokeExact可能会更快,但当我尝试使用它时,我得到了一个java.lang.invoke.WrongMethodTypeException
有没有人成功地优化了对Field.set或Field.get的重复调用?
我的问题与 该线程中显式使用LambdaMetafactory密切相关,提供了一些非常好的例子来使用LambdaMetafactory访问类的静态方法; 但是,我想知道访问现有bean实例的非静态字段的等效代码是什么.似乎很难找到一个例子,我所执行的每一次尝试都以非工作代码结束.
这是bean代码:
class SimpleBean {
private Object obj= "myCustomObject";
private static Object STATIC_OBJECT = "myCustomStaticObject";
public Object getObj() {
return obj;
}
public void setObj(final Object obj) {
this.obj = obj;
}
public static Object getStaticObj() {
return STATIC_OBJECT;
}
public static void setStaticObj(final Object obj) {
STATIC_OBJECT = obj;
}
}
Run Code Online (Sandbox Code Playgroud)
这里是一个成功访问静态方法"getStaticObj()"的工作单元测试:
@Test
public void accessStaticMethod() throws Throwable
{
MethodHandles.Lookup caller = MethodHandles.lookup();
Method reflected = SimpleBean.class.getDeclaredMethod("getStaticObj");
MethodHandle methodHandle = caller.unreflect(reflected);
CallSite site = LambdaMetafactory.metafactory(caller, …Run Code Online (Sandbox Code Playgroud) 我想尝试避免反射调用构造函数,并尝试遵循本文中采用的LamdaMetaFactory方法 - 更快地替代Java的反射
我想要构建的类看起来像:
interface DBBroker {}
public class NativeBroker implements DBBroker {
public NativeBroker(BrokerPool brokerPool, final Configuration configuration) {
}
}
Run Code Online (Sandbox Code Playgroud)
使用LambaMetaFactory我试图构造一个BiFunction<BrokerPool, Configuration, DBBroker>替换直接调用构造函数.
到目前为止我的代码看起来像:
Class<? extends DBBroker> clazz =
(Class<? extends DBBroker>) Class.forName("org.exist.storage.NativeBroker");
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh =
lookup.findConstructor(clazz, MethodType.methodType(void.class, new Class[] {BrokerPool.class, Configuration.class}));
BiFunction<BrokerPool, Configuration, DBBroker> constructor
(BiFunction<BrokerPool, Configuration, DBBroker>)
LambdaMetafactory.metafactory(
lookup, "apply", MethodType.methodType(BiFunction.class),
mh.type(), mh, mh.type()).getTarget().invokeExact();
final DBBroker broker = constructor.apply(database, conf);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会返回错误 -
AbstractMethodError:方法org/exists/storage/BrokerFactory $$ Lambda $ 55.apply(Ljava/lang/Object; Ljava/lang/Object;)Ljava/lang/Object; …
在我的工作中,我们有一个用于指定数学公式的DSL,我们后来应用于很多点(数百万).
截至今天,我们构建公式的AST,并访问每个节点以产生我们称之为"评估者"的东西.然后,我们向该求值程序传递公式的参数,并为每个点进行计算.
例如,我们有这个公式: x * (3 + y)
??????
???????mult???????
? ?????? ?
? ?
???v??? ???v???
? x ? ????? add ????
??????? ? ??????? ?
? ?
???v??? ???v???
? 3 ? ? y ?
??????? ???????
Run Code Online (Sandbox Code Playgroud)
我们的评估员将为每个步骤发出"评估"对象.
这种方法易于编程,但效率不高.
所以我开始研究方法句柄来构建一个"组合"的方法句柄,以加快最近的速度.
这样的事情:我有我的"算术"课:
public class Arithmetics {
public static double add(double a, double b){
return a+b;
}
public static double mult(double a, double b){
return a*b;
}
}
Run Code Online (Sandbox Code Playgroud)
在构建我的AST时,我使用MethodHandles.lookup()来直接获取它们的句柄并组合它们.沿着这些方向的东西,但在一棵树上:
Method add = ArithmeticOperator.class.getDeclaredMethod("add", double.class, double.class);
Method mult = ArithmeticOperator.class.getDeclaredMethod("mult", double.class, …Run Code Online (Sandbox Code Playgroud) 我正在比较性能MethodHandle::invoke和直接静态方法调用.这是静态方法:
public class IntSum {
public static int sum(int a, int b){
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的基准:
@State(Scope.Benchmark)
public class MyBenchmark {
public int first;
public int second;
public final MethodHandle mhh;
@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public int directMethodCall() {
return IntSum.sum(first, second);
}
@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public int finalMethodHandle() throws Throwable {
return (int) mhh.invoke(first, second);
}
public MyBenchmark() {
MethodHandle mhhh = null;
try {
mhhh = MethodHandles.lookup().findStatic(IntSum.class, "sum", MethodType.methodType(int.class, int.class, int.class));
} catch (NoSuchMethodException …Run Code Online (Sandbox Code Playgroud) 考虑weightclass 中的一个字段Animal。我希望能够创建用于操作此字段的getter和setter功能接口对象。
class Animal {
int weight;
}
Run Code Online (Sandbox Code Playgroud)
我目前的方法类似于用于方法的方法:
public static Supplier getter(Object obj, Class<?> cls, Field f) throws Exception {
boolean isstatic = Modifier.isStatic(f.getModifiers());
MethodType sSig = MethodType.methodType(f.getType());
Class<?> dCls = Supplier.class;
MethodType dSig = MethodType.methodType(Object.class);
String dMthd = "get";
MethodType dType = isstatic? MethodType.methodType(dCls) : MethodType.methodType(dCls, cls);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle fctry = LambdaMetafactory.metafactory(lookup, dMthd, dType, dSig, lookup.unreflectGetter(f), sSig).getTarget();
fctry = !isstatic && obj!=null? fctry.bindTo(obj) : fctry;
return (Supplier)fctry.invoke(); …Run Code Online (Sandbox Code Playgroud) java ×6
java-8 ×4
lambda ×3
methodhandle ×2
performance ×2
reflection ×2
field ×1
jit ×1
jmh ×1
jvm ×1