Reputation: 1866
As you all know it is possible to fetch a method with Reflection
and invoke it through the returned Method
instance.
My question is however; once it is fetched by Reflection
and I invoke the Method
over and over again will the performance of the method be slower than the normal way of calling a method?
For example:
import java.lang.reflect.Method;
public class ReflectionTest {
private static Method test;
public ReflectionTest() throws Exception {
test = this.getClass().getMethod("testMethod", null);
}
public void testMethod() {
//execute code here
}
public static void main(String[] args) throws Exception {
ReflectionTest rt = new ReflectionTest();
for (int i = 0; i < 1000; i++) {
rt.test.invoke(null, null);
}
for (int i = 0; i < 1000; i++) {
rt.testMethod();
}
}
}
I am asking this because I am making an event system that, upon registering the listener it scans for annotations. The methods are put into a map and then they are executed each time an event occurs of their required parameter type. I don't know if this is performant enough for, for example a game.
Upvotes: 5
Views: 308
Reputation: 718758
@Elliot Frisch's answer provides conclusive1 evidence that using Method.invoke()
is slower.
You would expect this anyway, because the reflective version involves extra work; e.g.
Object
to the respective parameter types.It is possible that the JIT could could optimize this in some cases ...
1 - OK ... inconclusive. The benchmark is questionable because it doesn't take proper care to deal with possible JVM warmup anomalies.
Upvotes: 2
Reputation: 201429
Using the method without reflection is about an order of magnitude faster. I tested it like
public static void main(String[] args) throws Exception {
ReflectionTest rt = new ReflectionTest();
// Warm up
for (int i = 0; i < 100; i++) {
test.invoke(rt, null);
}
for (int i = 0; i < 100; i++) {
rt.testMethod();
}
long start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
test.invoke(rt, null);
}
long end = Math.abs((start - System.nanoTime()) / 1000);
start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
rt.testMethod();
}
long end2 = Math.abs((start - System.nanoTime()) / 1000);
System.out.printf("%d %d%n", end, end2);
}
I also moved test
to a static
field so it would compile and run
private static Method test;
static {
try {
test = ReflectionTest.class.getMethod("testMethod");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
I get a fairly consistent difference (or an output consistent) with
4526 606
Which indicates that across 10000
invocations reflection is ~7 times slower then direct invocation.
Upvotes: 3