`I'm trying to fetch the execution time of a getName() method of Person's class by using LambdaMetaFactory instead of using AOP to improve the performance.
But Facing below exception when tried with the code mentioned:
Exception in thread "main" java.lang.AbstractethodError : Receiver Class does not define or inherit an implementation of the resolved method 'abstract void invoke ()' of interface GetterFunction.`
MyCode:
public class MyMain {
public static void main(String[] args) throws Throwable {
GetterFunction getterFunction;
final MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(String.class, Person.class);
final CallSite site = LambdaMetafactory.metafactory(lookup,
"invoke",
MethodType.methodType(GetterFunction.class),
methodType,
lookup.findVirtual(Person.class, "getName", MethodType.methodType(String.class)),
methodType);
getterFunction = (GetterFunction) site.getTarget().invokeExact();
getterFunction.invoke());
}
void invoke(GetterFunction getterFunction){
long startTime = System.CurrentMilliSeconds();
for(int i= 0 ; i<3 ; i++){
getterFunction.invoke();
}
long endTime = System.CurrentMilliSeconds();
System.out.println("Executed Time of a method :: "+ (endTime - startTime));
}
@FunctionalInterface
interface GetterFunction {
void invoke();
}
static class Person {
String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}`
Despite your question's title, your issue is not related to benchmarking execution time, but rather how to implement a functional interface dynamically via
LambdaMetafactory. I strongly recommend reading the documentation to properly understand the API.Everything below discusses the issues you are having with
LambdaMetafactory. There is nothing about writing benchmarking code. I recommend reading How do I write a correct micro-benchmark in Java? for such information. In short, you should use a framework like the Java Microbenchmark Harness (JMH).The Exception
The
AbstractMethodErroryou are seeing is due to passing an incorrectMethodTypeargument for theinterfaceMethodTypeparameter. You are passing:But that does not match your
GetterFunction::invoke()method whose return type isvoid, notString, and which as zero parameters, not a single parameter of typePerson. Thus, you have not actually implemented theinvokemethod. Technically, you should be passing:However, while that will solve the immediate error, it will not give you what you want. The code has other issues.
Functional Interface API
Your
GetterFunctioninterface is clearly meant to be a "getter proxy". When you callinvokeit is supposed to return the value of some object's property. Unfortunately, you defined the return type to bevoid, which means it cannot return anything. You need to fix the return type. Presumably you want this interface to be able to work with any property type, so you should make the interface generic and haveinvokereturnT.Capturing vs Argument
You should also consider whether you want to capture an instance of the object you want to call a getter on, or if you want to give
invokea parameter so that you can pass any object of a given type.Capturing
If you were to implement the above
GetterFunctionas a lambda it would look like:That lambda has captured the
personinstance. Each call togetter.invoke()will return the name of that specific person. An upside to this approach is that you do not need to keep an explicit reference to the person in order to call the getter. But a downside is that you can never change which person you invoke the getter on.You have to represent this capturing when creating a
GetterFunctionviaLambdaMetafactoryas well. This is done via thefactoryTypeargument. In this case, the argument would be:And then you would need to pass a
Personwhen creating theGetterFunction:Argument
The other option to capturing the object is to give
invokea parameter.An upside to this is that you can create a single
GetterFunctionfor a given property and then use it with any instance ofT. A downside is that you now have to have a direct reference toTin order to callinvoke.Note implementing this
GetterFunctionas a lambda would look like:No more capturing of a
Person.Working Example
Here is an example that implements a functional interface via
LambdaMetafactory. Note this example does not include any benchmark code.Ouptut: