如何比较两个MethodHandle实例?如果句柄指向相同的方法,我期望该函数返回 true。它看起来不像类覆盖equals()或hashcode()。使用相等运算符 ( ==) 安全吗?
我尝试在我的一个脚本中获得最大性能,而不进行重大重构。
我发现了使用反射从 Field 创建 BiConsumer 的方法。
return (c, v) -> {
try {
field.set(c, v);
} catch (final Throwable e) {
throw new RuntimeException("Could not set field: " + field, e);
}
};
Run Code Online (Sandbox Code Playgroud)
反射有缓慢的名声。所以我想我可以使用方法句柄。
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);
}
};
Run Code Online (Sandbox Code Playgroud)
这已经快了一点点。然而BiConsumer,它FunctionalInterface可以以某种方式生成。
public static <C, V> BiConsumer<C, V> …Run Code Online (Sandbox Code Playgroud) 我想以尽可能高效的方式通过反射调用方法。
\n该方法返回一个原语long。
我已经使用反射和MethodHandles 实现了这一点。
我期待MethodHandle更快,因为:
MethodHandle这就是s的好处之一但在我的所有基准测试中,MethodHandles 速度较慢(~2-5% 左右)。
采用以下 JMH 基准测试:
\nimport org.openjdk.jmh.annotations.*;\n\nimport java.lang.invoke.MethodHandle;\nimport java.lang.invoke.MethodHandles;\nimport java.lang.reflect.Method;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\n@BenchmarkMode(Mode.AverageTime)\n@OutputTimeUnit(TimeUnit.NANOSECONDS)\n@Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)\n@Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS)\n@State(Scope.Benchmark)\npublic class AccessorBenchmark {\n private POJO source;\n\n private ReflectionAccessor reflectionAccessor;\n private MethodHandleAccessor methodHandleAccessor;\n\n @Setup\n public void setup() throws ReflectiveOperationException {\n source = new POJO();\n\n final Method …Run Code Online (Sandbox Code Playgroud) import java.lang.invoke.*;
public class InvokeDynamicDemo {
public static double doubleIt(double d){
System.out.print("Doubling it");
return d*2;
}
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookUp = MethodHandles.lookup();
MethodHandle doubleIt = lookUp.findStatic(InvokeDynamicDemo.class, "doubleIt", MethodType.methodType(double.class,double.class));
doubleIt.invokeExact(2.0D); // Exception
//doubleIt.invoke(2.0D); // No exception thrown
}
}
Run Code Online (Sandbox Code Playgroud)
线程"main"中的异常java.lang.invoke.WrongMethodTypeException:expected(double)double但在java.lang.invoke.Invokers的java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:340)中找到(double)void InvokeDynamicDemo.main中的.checkExactType(Invokers.java:351)(InvokeDynamicDemo.java:32)
这段代码出了什么问题,我无法理解.请帮忙.
可以看出(请参见下面重写的测试用例),当由其工具编译和运行时,254 元方法的方法句柄在 Java 17 中占用的内存少于 Java 11 中的内存。
由于 Java 版本11到17的发行摘要中没有宣传与方法句柄或反射相关的功能,所以我很好奇:哪些变化有助于减少内存消耗?
这是一个重写的测试用例ArityLimits.java:
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
class ArityLimits
{
public static void main(String[] args) throws Throwable
{
// Pick an implementation with the 1st argument, e.g. core.
final Invocable invocable = (args.length > 0
&& args[0].equalsIgnoreCase("core"))
? new CoreInvoker(ArityLimits::new)
: new HandleInvoker(ArityLimits::new,
MethodHandles.privateLookupIn( …Run Code Online (Sandbox Code Playgroud)