public class InvocationBenchmark implements InvocationBenchmarkIntf { public final static int REPEAT = 10000000; public int aVirtualMethod(int n) { return n - 1; } private int aSpecialMethod(int n) { return n - 1; } public int aInterfaceMethod(int n) { return n - 1; } public static int aStaticMethod(int n) { return n - 1; } public static void main(String[] args) { InvocationBenchmark obj = new InvocationBenchmarkDerived(); benchmark(obj); } public static void benchmark(InvocationBenchmark obj) { long t0, t1, t2, t3; int n; InvocationBenchmarkIntf intf = (InvocationBenchmarkIntf)obj; // Invoke these methods in advance to compile them System.out.print(obj.aVirtualMethod(1)); System.out.print(obj.aSpecialMethod(1)); System.out.print(obj.aInterfaceMethod(1)); System.out.print(obj.aStaticMethod(1)); // invokevirtual n = REPEAT; t0 = -System.currentTimeMillis(); while (n > 0) { n = obj.aVirtualMethod(n); // This invocation certainly raises a dynamic resolution of // the callee method. This invocation may be treated as // a static invocation if this benchmark() method is inlined // into main() and type propagation is performed. // But this case may not happen. } t0 += System.currentTimeMillis(); System.out.print(n); // invokespecial n = REPEAT; t1 = -System.currentTimeMillis(); while (n > 0) { n = obj.aSpecialMethod(n); } t1 += System.currentTimeMillis(); System.out.print(n); // invokeinterface n = REPEAT; t2 = -System.currentTimeMillis(); while (n > 0) { n = intf.aInterfaceMethod(n); } t2 += System.currentTimeMillis(); System.out.print(n); // invokestatic n = REPEAT; t3 = -System.currentTimeMillis(); while (n > 0) { n = InvocationBenchmark.aStaticMethod(n); } t3 += System.currentTimeMillis(); System.out.print(n); System.out.println(); System.out.println("virtual : " + t0); System.out.println("special : " + t1); System.out.println("interface: " + t2); System.out.println("static : " + t3); System.out.println(" (msec / " + REPEAT + " times)"); } }