views:

5073

answers:

10

Does creating an object using reflection rather than calling the class constructor result in any significant performance differences?

+5  A: 

Yes, it is significantly slower. We were running some code that did that, and while I don't have the metrics available at the moment, the end result was that we had to refactor that code to not use reflection. If you know what the class is, just call the constructor directly.

Elie
+1 I've had a similar experience. It's good to make sure to only use reflection if it's absolutely necessary.
Ryan Thames
+31  A: 

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();
 }
 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();
 }
 System.out.println(System.currentTimeMillis() - start);
}
}

With these results:

15 // no reflection
1781 // 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 factor of 10 decrease in performance:

16 // no reflection
172 // reflection using one lookup, only instantiating

Again, YMMV.

Yuval A
On my machine the .newInstance() call with only one Class.forName() call scores 30 or so. Depending on VM version, the difference may be closer than you think with an appropriate caching strategy.
Sean Reilly
On my system (a dual core 2.4 GHz), I see times of - Instantiate: 7.8, Reflect 1: 171.9, and Reflect 2: 3181.3 (where reflect 2 is the reflection as above, and 1 is the reflection with forName done only once - all times are for 1,000,000 iterations).
Software Monkey
Also, this performance factor depends very much on the cost of the object initialization - i.e. the work done in the constructor.
Software Monkey
Dude, thanks for working up the numbers on this. I see reflection used in server-side code, and it gives me the willies. ;)
Don Branson
+11  A: 

There is some overhead with reflection, but it's a lot smaller on modern VMs than it used to be.

If you're using reflection to create every simple object in your program then something is wrong. Using it occasionally, when you have good reason, shouldn't be a problem at all.

Marcus Downing
A: 

Yes, always will be slower create an object by reflection because the JVM cannot optimize the code on compilation time. See the Sun/Java Reflection tutorials for more details.

See this simple test:

public class TestSpeed {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        Object instance = new TestSpeed();
        long endTime = System.nanoTime();
        System.out.println(endTime - startTime + "ns");

        startTime = System.nanoTime();
        try {
            Object reflectionInstance = Class.forName("TestSpeed").newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        endTime = System.nanoTime();
        System.out.println(endTime - startTime + "ns");
    }
}
aledbf
Note that you should separate the lookup (`Class.forName()`) from the instanciation (newInstance()), because they vary significantly in their performance characteristics and you can occasionally avoid the repeated lookup in a well-designed system.
Joachim Sauer
Also: you need to execute each task many, many times to get a useful benchmark: first of all the actions are too slow to be measured reliably and secondly you'll need to warm up the HotSpot VM to get useful numbers.
Joachim Sauer
+4  A: 

"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.

kdgregory
+1  A: 

Often you can use Apache commons BeanUtils or PropertyUtils which introspection (basically they cache the meta data about the classes so they don't always need to use reflection).

Dan Howard
+4  A: 

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.

Peter Lawrey
so you've just killed the optimiser, so now both versions are slow. Reflection is, therefore, still damn slow.
gbjbaanb
+6  A: 

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".

Bill K
I totally agree with the sentiment of this response, however if you're about to embark upon a major design decision it helps to have an idea about performance so you don't go off on a totally unworkable path. Maybe he's just doing due diligence?
Limbic System
-1: Avoiding doing things the wrong way is not optimisation, it is just doing things. Optimisation is doing things the wrong, complicated way because of either real or imaginary performance concerns.
soru
@soru totally agree. Choosing a linked list over an array list for an insertion sort is simply the right way to do things. But this particular question--there are good use cases for both sides of the original question, so choosing one based on performance rather than the most usable solution would be wrong. I'm not sure we are disagreeing at all, so I'm not sure why you said "-1".
Bill K
Because you shouldn't mention performance as an issue at all until it has been established as the right thing to do.In this context, constructor for objects inside your type-checking/compilation 'world', reflection for things outside it. Performance is like price, just because something is expensive doesn't in itself make it better. A $10 digital watch probably tells the time as well or better than a $30,000 platinum chunk of bling.
soru
@soru that's exactly what I said. Still not sure why you feel we are disagreeing. Did you possibly misread my post? "You must never optimize until you are sure you need it" == "you shouldn't mention performance as an issue at all until it has been established as the right thing to do."
Bill K
Any sensible analyst programmers needs to consider efficiency at an early stage or you might end up with a system that can NOT be optimised in an efficient and costworthy timeframe. No, you dont optimise every clock cycle but you most certainly DO employ best practices for something as basic as class instantiation. This example is a great one of WHY you consider such questions regarding reflection. It would be a pretty poor programmer who went ahead and used reflection throughout a million line system only to later discover it was orders of magnitude too slow.
Richard Riley
@Richard Riley Generally class instantiation is a pretty rare event for the selected classes you will use reflection on. I suppose you are right though--some people might instantiate every class reflectively, even ones that are recreated constantly. I would call that pretty bad programming (although even then you COULD implement a cache of class instances for reuse after the fact and not harm your code too much--so I guess I'd still say ALWAYS design for readability, then profile and optimize later)
Bill K
+1  A: 

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.

Esko Luontola
+2  A: 

Be careful of the benchmarks posted above! They are flawed. See this post: http://stackoverflow.com/questions/647111/newinstance-vs-new

Idris