Dealing with Legacy Code in OpenJDK (JEP 416)

I've just seen JEP 416: Reimplement Core Reflection with Method Handles has been promoted to Candidate status ("Candidate: Accepted for inclusion in the OpenJDK roadmap"), and thought I'd find out a bit more about it.

The JEP is an implementation change, not an API change - so those of us who use reflection won't see any changes in the names of the methods we use or any new features. My first thought was that the driving force behind this JEP is performance - "everyone knows" reflection is slow, and I assume Method Handles (introduced in Java 7) are faster (based on absolutely zero experience or benchmarking on my part).

The reason for the change is actually more interesting (to me). This is one of those cases where we can see Java (a 26-year-old language) suffers from the same problem as any sufficiently mature application - how can we move forward with all this old code/design dragging us back?

The JEP says that reflection uses some special code to do what it does (I was particularly tickled by jdk.internal.reflect.MagicAccessorImpl, which reminded me of Open Source Projects Aren't Magic by Jenn Strater). When you consider this, plus the "normal" way of calling methods and method handles too, there are three different paths that need updating if any changes need to be made in this area. The JEP specifically calls out language features in Project Valhalla as needing to make these changes.

So the motivation for JEP 416 is to change the implementation of reflection to make it easier to make changes that evolve the language.

I like this, I like that some changes to OpenJDK show an approach to dealing with "legacy" (i.e. working) code that maintains backwards compatibility and enables, or simplifies, the addition of new features. It's tricky to balance this, and often we complain about "Tech Debt" stopping us from moving forward, when in fact it's not debt at all - it's not a shortcut or temporary approach taken that we know we have to address later, it's a perfectly acceptable design decision taken years ago that needs to be re-addressed and evolved now new requirements have come to light. Taking the time to consolidate or simplify implementation at strategic points when it makes sense given some known new requirements is a good way to make progress.

And guess what? In this case, it looks like it might even lead to performance improvements too: "Microbenchmarks show no significant performance regressions as well as improvements in many cases." Double win!

Author

  • Trisha Gee

    Trisha is a software engineer, Java Champion and author. Trisha has developed Java applications for finance, manufacturing and non-profit organisations, and she's a lead developer advocate at Gradle.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.