An Application Architect for Myriad Genetics, Ian Robertson has been toiling away at the Java coalface for 14 years, during which time he has amassed a fairly hefty open source project portfolio. Here, walks us through the ins-and-outs of his JavaOne 2014 talk, ‘Supercharging Reflective Libraries with InvokeDynamic.’
What’s your background working with InvokeDynamic, and what inspired you to put your talk ‘Supercharging Reflective Libraries with InvokeDynamic’ together?
I’ve worked on Pojomatic, an open source project, for the last few years. It greatly simplifies the creation of the standard equals, hashCode and toString methods on Object. Version 1.0 used reflection, and while in most cases it performed adequately, it still was an order of magnitude slower than what could be achieved by writing those methods by hand. Bytecode generation was not an option, because compiled classes would not be able to access private fields and methods of other classes.
With the introduction of InvokeDynamic in Java 7, it became possible to generate bytecode that could access any fields or methods that could be otherwise accessed via reflection. I was curious to try it out, both as a learning exercise and as a way to improve performance. I ended up being quite happy on both fronts!
How would you begin to go about about transforming a traditional reflection-based library with InvokeDynamic and bytecode generation, and what would be the motivation for doing this?
The first step is to make sure it’s worth doing! Bytecode generation is a fair amount harder than traditional java coding, both in upfront work and in maintenance. So before you start trying to generate bytecode, hand code a class that corresponds roughly to the bytecode you would want to generate, and benchmark that against your existing reflection-based code. Bear in mind that while InvokeDynamic will be faster than reflection, the JIT optimizer does not always manage to get it performing as fast as traditional bytecode would (at least not yet!)
What issues might there be in doing this?
Debugging becomes much harder, since there is no java source code to match up with your generated byte code. Because of this, you also want to make sure that your code is solid, so that your clients don’t have to worry about this. Lots of automated testing is key here!
You also talked about creating a simple JSON marshalling library by using ASM bytecode generation and InvokeDynamic and demonstrated how hand-rolled marshaling code can be rivaled in performance. Can you walk us through this?
The first step is to have ASM’s Asmifier class generate some sample code for you that in turn can generate sample bytecode. Using this as a sort of template, you can write code that will dynamically generate the bytecode you want. The next step is to take any field or method invocations that might have to go against private members and replace them with InvokeDynamic calls. Finally, create a classloader that can load the bytecode you generated to turn it into a regular old Java class.
How would readers test their code?
Automated testing is absolutely essential for this type of endeavour. There are a number of different variables that need to be considered, and they can all interact with each other. You need to consider what happens when a property type is primitive, an array, a multidimensional array, etc. You need to handle inheritance, including the case where private variables in a superclass and subclass have the same name. Inner classes can pose their own challenges as well. When I converted Pojomatic to use InvokeDymanic, I ended up writing data-driven tests that would cover all combinations of these. Ironically, to do this required bytecode generation to create the various kinds of classes!
Did any interesting questions arise from this talk?
I think the most interesting question was something to the effect of “Is this really worth it”? It’s a hard question to answer. I think in most cases, the answer is probably “no”. However, if a library has the potential to be run in performance-critical sections of code, and if you feel like digging into the JVM (as opposed to just the Java Language), it can definitely be worth it.
More from Ian:
Code samples from the talk: https://github.com/irobertson/invokedynamic-talk-code