Java Reflection Performance Java Reflection Performance java java

Java Reflection Performance


Yes - absolutely. Looking up a class via reflection is, by magnitude, more expensive.

Quoting Java's documentation on reflection:

Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

Here's a simple test I hacked up in 5 minutes on my machine, running Sun JRE 6u10:

public class Main {    public static void main(String[] args) throws Exception    {        doRegular();        doReflection();    }    public static void doRegular() throws Exception    {        long start = System.currentTimeMillis();        for (int i=0; i<1000000; i++)        {            A a = new A();            a.doSomeThing();        }        System.out.println(System.currentTimeMillis() - start);    }    public static void doReflection() throws Exception    {        long start = System.currentTimeMillis();        for (int i=0; i<1000000; i++)        {            A a = (A) Class.forName("misc.A").newInstance();            a.doSomeThing();        }        System.out.println(System.currentTimeMillis() - start);    }}

With these results:

35 // no reflection465 // using reflection

Bear in mind the lookup and the instantiation are done together, and in some cases the lookup can be refactored away, but this is just a basic example.

Even if you just instantiate, you still get a performance hit:

30 // no reflection47 // reflection using one lookup, only instantiating

Again, YMMV.


Yes, it's slower.

But remember the damn #1 rule--PREMATURE OPTIMIZATION IS THE ROOT OF ALL EVIL

(Well, may be tied with #1 for DRY)

I swear, if someone came up to me at work and asked me this I'd be very watchful over their code for the next few months.

You must never optimize until you are sure you need it, until then, just write good, readable code.

Oh, and I don't mean write stupid code either. Just be thinking about the cleanest way you can possibly do it--no copy and paste, etc. (Still be wary of stuff like inner loops and using the collection that best fits your need--Ignoring these isn't "unoptimized" programming, it's "bad" programming)

It freaks me out when I hear questions like this, but then I forget that everyone has to go through learning all the rules themselves before they really get it. You'll get it after you've spent a man-month debugging something someone "Optimized".

EDIT:

An interesting thing happened in this thread. Check the #1 answer, it's an example of how powerful the compiler is at optimizing things. The test is completely invalid because the non-reflective instantiation can be completely factored out.

Lesson? Don't EVER optimize until you've written a clean, neatly coded solution and proven it to be too slow.


You may find that A a = new A() is being optimised out by the JVM.If you put the objects into an array, they don't perform so well. ;)The following prints...

new A(), 141 nsA.class.newInstance(), 266 nsnew A(), 103 nsA.class.newInstance(), 261 nspublic class Run {    private static final int RUNS = 3000000;    public static class A {    }    public static void main(String[] args) throws Exception {        doRegular();        doReflection();        doRegular();        doReflection();    }    public static void doRegular() throws Exception {        A[] as = new A[RUNS];        long start = System.nanoTime();        for (int i = 0; i < RUNS; i++) {            as[i] = new A();        }        System.out.printf("new A(), %,d ns%n", (System.nanoTime() - start)/RUNS);    }    public static void doReflection() throws Exception {        A[] as = new A[RUNS];        long start = System.nanoTime();        for (int i = 0; i < RUNS; i++) {            as[i] = A.class.newInstance();        }        System.out.printf("A.class.newInstance(), %,d ns%n", (System.nanoTime() - start)/RUNS);    }}

This suggest the difference is about 150 ns on my machine.