Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing Java code that compiles using one of two implementations of a class

I am writing some FFI code in Java that makes heavy use of sun.misc.Unsafe.

In Java 9, this class will become inaccessible, and will become jdk.unsupported.Unsafe. I would like to write my code so that it works now, but continues to work in Java 9.

What is the least hacky way to do this? I would prefer binary compatibility, but source compatibility is also okay.

Edit: I am 100% not okay with using reflection – or even virtual dispatch – every time a method on Unsafe is called. Most of those methods compile to a single machine instruction. Therefore, performance really matters. It's okay to have wrappers – but only if I can be sure the JIT will inline them, every time.

My current plan is to load an appropriate class at runtime.

like image 755
Demi Avatar asked Oct 15 '16 18:10

Demi


1 Answers

One option: You could have a small shim helper interface for the method(s) on Unsafe that you need access to, with two implementations: one for sun.misc.Unsafe and one for the new jdk.unsupported.Unsafe. Both classes could be stored as binary resources in your JAR, and during class initialization (that is, in a static block) you could create a new ClassLoader and load the shim class. This would give you some reflective overhead during class initialization, but at runtime there's no reflection involved, only a virtual method dispatch -- which the JIT should be able to inline, so long as you only load the one implementation class.

If you can introduce a library dependency, cglib's FastClass will basically do this for you with a lot less effort.

As always with low-level performance hacks like this, you need some data. Create a JMH test harness for this and verify that the reflection overhead really is intolerable, and that the JIT really can inline your solution -- that's the only way to be certain.

like image 171
Daniel Pryden Avatar answered Oct 09 '22 08:10

Daniel Pryden