Java Reflection Performance

ID : 20231

viewed : 14

Tags : javaperformanceoptimizationreflectionjava

Top 5 Answer for Java Reflection Performance

vote vote

100

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 reflection 465 // 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 reflection 47 // reflection using one lookup, only instantiating 

Again, YMMV.

vote vote

81

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.

vote vote

78

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 ns A.class.newInstance(), 266 ns new A(), 103 ns A.class.newInstance(), 261 ns  public 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.

vote vote

64

If there really is need for something faster than reflection, and it's not just a premature optimization, then bytecode generation with ASM or a higher level library is an option. Generating the bytecode the first time is slower than just using reflection, but once the bytecode has been generated, it is as fast as normal Java code and will be optimized by the JIT compiler.

Some examples of applications which use code generation:

  • Invoking methods on proxies generated by CGLIB is slightly faster than Java's dynamic proxies, because CGLIB generates bytecode for its proxies, but dynamic proxies use only reflection (I measured CGLIB to be about 10x faster in method calls, but creating the proxies was slower).

  • JSerial generates bytecode for reading/writing the fields of serialized objects, instead of using reflection. There are some benchmarks on JSerial's site.

  • I'm not 100% sure (and I don't feel like reading the source now), but I think Guice generates bytecode to do dependency injection. Correct me if I'm wrong.

vote vote

58

"Significant" is entirely dependent on context.

If you're using reflection to create a single handler object based on some configuration file, and then spending the rest of your time running database queries, then it's insignificant. If you're creating large numbers of objects via reflection in a tight loop, then yes, it's significant.

In general, design flexibility (where needed!) should drive your use of reflection, not performance. However, to determine whether performance is an issue, you need to profile rather than get arbitrary responses from a discussion forum.

Top 3 video Explaining Java Reflection Performance

Related QUESTION?