簡單的解決辦法是寫一個更現實的基準,這確實有用差不多的東西,這樣就不會被優化掉。
有一些竅門來迷惑JIT的,但這些都不可能幫助你。
下面是示例的,其中該方法是通過反射,MethodHandle叫和編譯以什麼基準的。
import java.lang.invoke.*;
import java.lang.reflect.*;
public class Main {
public static void main(String... args) throws Throwable {
for (int j = 0; j < 5; j++) {
testViaReflection();
testViaMethodHandle();
testWithoutReflection();
}
}
private static void testViaReflection() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Method nothing = Main.class.getDeclaredMethod("nothing");
int runs = 10000000; // triggers a warmup.
long start = System.nanoTime();
Object[] args = new Object[0];
for (int i = 0; i < runs; i++)
nothing.invoke(null, args);
long time = System.nanoTime() - start;
System.out.printf("A call to %s took an average of %.1f ns using reflection%n", nothing.getName(), 1.0 * time/runs);
}
private static void testViaMethodHandle() throws Throwable {
MethodHandle nothing = MethodHandles.lookup().unreflect(Main.class.getDeclaredMethod("nothing"));
int runs = 10000000; // triggers a warmup.
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
nothing.invokeExact();
}
long time = System.nanoTime() - start;
System.out.printf("A call to %s took an average of %.1f ns using MethodHandle%n", "nothing", 1.0 * time/runs);
}
private static void testWithoutReflection() {
int runs = 10000000; // triggers a warmup.
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
nothing();
long time = System.nanoTime() - start;
System.out.printf("A call to %s took an average of %.1f ns without reflection%n", "nothing", 1.0 * time/runs);
}
public static void nothing() {
// does nothing.
}
}
打印
A call to nothing took an average of 6.6 ns using reflection
A call to nothing took an average of 10.7 ns using MethodHandle
A call to nothing took an average of 0.4 ns without reflection
A call to nothing took an average of 4.5 ns using reflection
A call to nothing took an average of 9.1 ns using MethodHandle
A call to nothing took an average of 0.0 ns without reflection
A call to nothing took an average of 4.3 ns using reflection
A call to nothing took an average of 8.8 ns using MethodHandle
A call to nothing took an average of 0.0 ns without reflection
A call to nothing took an average of 5.4 ns using reflection
A call to nothing took an average of 13.2 ns using MethodHandle
A call to nothing took an average of 0.0 ns without reflection
A call to nothing took an average of 4.9 ns using reflection
A call to nothing took an average of 8.7 ns using MethodHandle
A call to nothing took an average of 0.0 ns without reflection
我曾以爲MethodHandles比反射快,但它不會出現如此。
使用結果。 –
可惜,這從來沒有得到真正的答案。 +1爲「爲什麼我必須在許多評論中重新解釋我的問題」綜合症的團結。 – sqykly