I try to get the maximum performance in one of my scripts, without doing a major refactor.
I spotted method that creates a BiConsumer from a Field using reflection.
return (c, v) -> {
try {
field.set(c, v);
} catch (final Throwable e) {
throw new RuntimeException("Could not set field: " + field, e);
}
};
Reflection has the reputation of being slow. So I though I could use the method handles.
Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.unreflectSetter(field);
return (c, v) -> {
try {
mh.invoke(c, v);
} catch (final Throwable e) {
throw new RuntimeException("Could not set field: " + field, e);
}
};
Which is already a tiny bit faster. However BiConsumer
is a FunctionalInterface
which could just be generated somehow.
public static <C, V> BiConsumer<C, V> createSetter(final MethodHandles.Lookup lookup,
final Field field) throws Exception {
final MethodHandle setter = lookup.unreflectSetter(field);
final CallSite site = LambdaMetafactory.metafactory(lookup,
"accept",
MethodType.methodType(BiConsumer.class),
MethodType.methodType(void.class, Object.class, Object.class), // signature of method BiConsumer.accept after type erasure
setter,
setter.type()); // actual signature of setter
return (BiConsumer<C, V>) site.getTarget().invokeExact();
}
However then I get an Exception which I don't really understand
Exception in thread "main" java.lang.invoke.LambdaConversionException: Unsupported MethodHandle kind: putField org.sample.dto.TestDTO.name:(String)void
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:182)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at org.sample.bench.MyBenchmark.createSetter(MyBenchmark.java:120)
at org.sample.bench.MyBenchmark.main(MyBenchmark.java:114)
In which way do I have to generate that setter correctly to increase the performance. (without actually adding a setter method)
Aucun commentaire:
Enregistrer un commentaire