Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of reflection: quality byte code in JVM

Edit 2: Does a program with a fully object-oriented implementation give high performance? Most of the framework is written with full power of it. However, reflection is also heavily used to achieve it like for AOP and dependency injection. Use of reflection affects the performance to a certain extent.

So, Is it good practice to use reflection? Is there some alternative to reflection from programming language constructs? To what extent should reflection be used?

like image 559
abishkar bhattarai Avatar asked Feb 05 '13 09:02

abishkar bhattarai


People also ask

How fast is reflection Java?

Adding setAccessible(true) call makes these reflection calls faster, but even then it takes 5.5 nanoseconds per call. Reflection is 106% slower than direct access (so about twice as slow). It also takes longer to warm up.

Why is reflection in Java slow?

Reflection is slow for a few obvious reasons: The compiler can do no optimization whatsoever as it can have no real idea about what you are doing. This probably goes for the JIT as well. Everything being invoked/created has to be discovered (i.e. classes looked up by name, methods looked at for matches etc)

What is JVM what is byte code?

In computing, Java bytecode is the bytecode-structured instruction set of the Java virtual machine (JVM), a virtual machine that enables a computer to run programs written in the Java programming language and several other programming languages, see List of JVM languages.

Why is reflection slow?

Reflection is slower Because it involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed.


3 Answers

Reflection is, in itself and by nature, slow. See this question for more details. This is caused by a few reasons. Jon Skeet explains it nicely:

Check that there's a parameterless constructor Check the accessibility of the parameterless constructor Check that the caller has access to use reflection at all Work out (at execution time) how much space needs to be allocated Call into the constructor code (because it won't know beforehand that the constructor is empty)

Basically, reflection has to perform all the above steps before invocation, whereas normal method invocation has to do much less.

The JITted code for instantiating B is incredibly lightweight. Basically it needs to allocate enough memory (which is just incrementing a pointer unless a GC is required) and that's about it - there's no constructor code to call really; I don't know whether the JIT skips it or not but either way there's not a lot to do.

With that said, there are many cases where Java is not dynamic enough to do what you want, and reflection provides a simple and clean alternative. Consider the following scenario:

  1. You have a large number of classes which represent various items, i.e. a Car, Boat, and House.
  2. They both extend/implement the same class: LifeItem.
  3. Your user inputs one of 3 strings, "Car", "Boat", or "House".
  4. Your goal is to access a method of LifeItem based on the parameter.
  5. The first approach that comes to mind is to build an if/else structure, and construct the wanted LifeItem. However, this is not very scalable and can become very messy once you have dozens of LifeItem implementations.

Reflection can help here: it can be used to dynamically construct a LifeItem object based on name, so a "Car" input would get dispatched to a Car constructor. Suddenly, what could have been hundreds of lines of if/else code turns into a simple line of reflection. The latter scenario would not be as valid on a Java 7+ platform due to the introduction of switch statements with Strings, but even then then a switch with hundreds of cases is something I'd want to avoid. Here's what the difference between cleanliness would look like in most cases:

Without reflection:

public static void main(String[] args) {
   String input = args[0];
   if(input.equals("Car"))
      doSomething(new Car(args[1]));
   else if(input.equals("Boat"))
      doSomething(new Boat(args[1]));
   else if (input.equals("House"))
      doSomething(new House(args[1]));
   ... // Possibly dozens more if/else statements
}

Whereas by utilizing reflection, it could turn into:

public static void main(String[] args) {    
   String input = args[0];
   try {
      doSomething((LifeItem)Class.forName(input).getConstructor(String.class).newInstance(args[1]));
   } catch (Exception ie) {
      System.err.println("Invalid input: " + input);
   }  
}

Personally, I'd say the latter is neater, more concise, and more maintainable than the first. In the end its a personal preference, but that's just one of the many cases where reflection is useful.

Additionally, when using reflection, you should attempt to cache as much information as possible. In other words employ simple, logical things, like not calling get(Declared)Method everywhere if you can help it: rather, store it in a variable so you don't have the overhead of refetching the reference whenever you want to use it.

So those are the two extremes of the pro's and con's of reflection. To sum it up if reflection improves your code's readability (like it would in the presented scenario), by all means go for it. And if you do, just think about reducing the number of get* reflection calls: those are the easiest to trim.

like image 83
Xyene Avatar answered Oct 19 '22 21:10

Xyene


While reflection is most expensive than "traditional code", premature optimization is the root of all evil. From a decade-long empirical evidence, I assume that a method invoked via reflection will hardly affect performance unless it is invoked from a heavy loop, and even so there have been some performance enhancements on reflection:

Certain reflective operations, specifically Field, Method.invoke(), Constructor.newInstance(), and Class.newInstance(), have been rewritten for higher performance. Reflective invocations and instantiations are several times faster than in previous releases Enhancements in J2SDK 1.4 -

Note that method lookup (i.e. Class.getMethod) is not mentioned above, and choosing the right Method object usually requires additional steps such as traversing the class hierarchy while asking for the "declared method" in case that it is not public), so I tend to save the found Method in a suitable map whenever it is possible, so that the next time the cost would be only that of a Map.get() and Method.invoke(). I guess that any well-written framework can handle this correctly.

One should also consider that certain optimizations are not possible if reflection is used (such as method inlining or escape analysis. Java HotSpot™ Virtual Machine Performance Enhancements). But this doesn't mean that reflection has to be avoided at all cost.

However, I think that the decision of using reflection should be based in other criteria, such as code readability, maintainability, design practices, etc. When using reflection in your own code (as opposed to using a framework that internally uses reflection), one risk transforming compile-time errors into run-time errors, which are harder to debug. In some cases, one could replace the reflective invocation by a traditional OOP pattern such as Command or Abstract Factory.

like image 21
Javier Avatar answered Oct 19 '22 21:10

Javier


I can give you one example (but sorry, I can't show you the test results, because it was few months ago). I wrote an XML library (custom project oriented) which replaced some old DOM parser code with classes + annotations. My code was half the size of the original. I did tests, and yes, reflection was more expensive, but not much (something like 0.3 seconds out of 14-15 seconds of executing (loss is about 2%)). In places, where code is executed infrequently, reflection can be used with a small performance loss.

Moreover, I am sure, that my code can be improved for better performance.

So, I suggest these tips:

  1. Use reflection if you can do it in a way that is beautiful, compact & laconic;
  2. Do not use reflection if your code will be executed many-many times;
  3. Use reflection, if you need to project a huge amount of information from another source (XML-files, for example) to Java application;
  4. The best usage for reflections and annotations is where code is executed only once (pre-loaders).
like image 2
Yorie Avatar answered Oct 19 '22 20:10

Yorie