The debate over Unsafe continues – “Overall Java 9 feels somehow broken”
The buzz around the plan to remove Unsafe from Java 9 has yet to subside, so we spoke to Technical Evangelist at Hazelcast Christoph Engelbert and founder of the Performance Java User’s Group Peter Lawrey about consequences and solutions.
JAXenter: There’s a plan to make sun.misc.Unsafe unavailable to users in JDK 9. What is the reason for this?
Christoph Engelbert: First of all I guess nobody disagrees on the plan. The API is horrible and it was never meant to be used in the first place but it was available and it was used. Let me come back to this a bit later.
One of the reasons to remove sun.misc.Unsafe is to make Java more secure. sun.misc.Unsafe offers random memory peak and poke without bounding checks and with memory access inlined into the optimized native code of the JIT compilers.
Peter Lawrey: While the API wasn’t standard, it was used because either:
- It was there
- It was fun
- It was better than using JNI
- There really was no alternative
For a long time it appeared the designers assumed that people were only using it because it was there or for fun and couldn’t understand why anyone would need it, except themselves, they definitely needed it, but no one else could possibly need it. What I found odd about this was the designers needed Unsafe to implement low level libraries, and appeared to assume no one else would need to also write low level libraries.
Now they realise, not long before Java 9 is released, that they can’t just take away Unsafe as it has been used in too many places. Very few internal APIs have been used by so many libraries. Note however that the tools.jar was taken away with relatively less concern, mostly because there was a better replacement, the Compiler API, and this had been around for some time.
Christoph: I guess Unsafe is the most used internal API to go away ever, not only in the Java ecosystem. As Peter already said a lot of things will disappear in Java 9 but sun.misc.Unsafe is probably the most used, but not the only one. The OpenJFX project for example still uses classes from com.sun.javafx since the code wasn’t open sourced (yet?). That means OpenJFX will not work out ot the box on Java 9, too.
The community has shown some resistance against the plan. Why do so many people see problems regarding the removal of the sun.misc.Unsafe API?
Christoph: As mentioned earlier it was available and used a lot. There are lots of different use cases and reasons like serialization, performance, latency, mocking frameworks and more that heavily rely on sun.misc.Unsafe. If the Unsafe API wouldn’t have been available in the first place, the Java ecosystem might look different today.
Peter: There are two problems. Users of the libraries don’t want their applications to break and might not be ready to upgrade. They want migration to Java 9 to be as smooth as possible. Having to worry about JVM changes and updating libraries, when there isn’t as much benefit to going to Java 9, makes it all the more likely that this won’t happen. Possibly, more people will jump to Java 10 once all the risks are better understood.
The second problem is for developers of the libraries. Initially it was announced that Unsafe was going away, but this missed the point that in most cases Unsafe was only used as there was no better alternative. Later it was suggest an alternative would be available in Java 9, but over time it appears that there won’t be a replacement ready for all functionality by the file Java 9’s feature set has to be frozen.
For code which has been used in production on many machines, Unsafe was used because there was no alternative, other than using another language. In some cases you could have used JNI and released DLLs and SOs for a range of platforms. Using JNI can be seen as a much greater risk and less safe than using an undocumented, but widely used, class.
However, in many cases JNI could not have performed as the intrinsics in Unsafe do. This means those “native” methods are replaced with one or more machine code instructions. i.e. intrinsics are much faster for trivial operations than using JNI.
Christoph: JNI has a huge overhead due to translation of data types between C and Java, it was always known to be the bottleneck in JNI. In addition, as Peter stated, Unsafe operations are nicely intrinsified, so the actual C code is never really used and you only have the direct, native memory access.
You asked for a proposal paper for technical solutions – how would something like this look?
Christoph: I was one of the initial creators of the Google Doc that started this huge discussion. As part of Hazelcast, and personally, I’m afraid of what will happen to the Java ecosystem when sun.misc.Unsafe eventually disappears forever. For now we already heard that there will be a command line parameter to “re-export” the hidden sun.misc package but how long will it stay? For now there are not a lot of alternatives or, like VarHandles, they don’t seem to solve the problem completely. We looked into VarHandles last week at JCrete and to provide solutions to a few problems, like fast array access, they still miss a lot of what it was supposed to solve. However, we work with the engineers to get at least the VarHandles right for Java 9.
Peter: The paper Christoph started was successful in getting the right people’s attention. I had attempted to start similar discussions before, but had no luck. What I have proposed in the past is to have an extension of the ByteBuffer API or one like it. Both Chronicle and Aeron do this and in our case, we have such a replacement which has been used in production for years. This covers only a subset of Unsafe operations but seems to be a more natural way to address the limitations in the API we had to work around, rather than inventing an entirely new one. The introduction of VarHandles feels like an overly complicated solution to what is fundamentally a single machine instruction to access raw memory, I am looking forward to see how it will work for off heap data structures.
Christoph: I don’t fully agree in this case, especially from the implementation side VarHandles seem extremely complicated, but most users won’t touch that anyways. On the other side I kind of like the VarHandles API, it moves the different implementations of Buffers, we currently have an array backed buffer, an Unsafe backed buffer, a ByteBuffer back buffer, to a single lightweight wrapper implementation over VarHandles, which (if correctly implemented) will unify access to all the different data storages.
You also proposed a Working Group. What are your expectations of the group?
Christoph: The Working Group is about to form and the idea is to combine all knowledge and engagement that is currently spread inside the Java community.
Peter: I think we need to demonstrate real world use cases so the JVM designers can work out what is the best way to solve them.
You mentioned VarHandles. Can you explain the idea and how it would solve some problems?
Christoph: We were at JCrete last week and had a heated discussion about the removal of Unsafe. Due to this discussion, I am currently taking a deep look into the VarHandles prototype and implementing first tests to figure out if it can really solve problems as promised and if speed keeps up. So far I found a couple of use cases that are not yet handled and am working with Paul Sandoz to solve those. VarHandles look like a first good step to a replacement API, however it will only replace the memory access parts of sun.misc.Unsafe – still a lot of functionalities are missing that need to be replaced.
Peter: Our main use case is off heap, shared, persistent data structures. The benefit is that we can use shared data between processes as fast as sharing data between threads. We can also persist that data in bursts of 30 million updates per second. One of our clients writes 24 million market data events per second during peak periods in the market. As the code is GC free, this is done without pauses. In the past, this might have only been achieved using C++ or C, but Unsafe allows us to get the performance of C where we need it but the portability and ease of development of Java.
Christoph: Yeah Peter is right here, VarHandles won’t solve this problem yet. As far as I can see, Project Panama will be a solution to this but it won’t show up before Java 10. Overall Java 9 feels somehow broken and as I said in the JCrete discussion, we may want to think about: “can’t we just skip Java 9”?
Peter: Maybe Java 9 will have the changes we had to have so we can move forward with the JVM platform, but from an end user’s point of view, it doesn’t appear as compelling as Java 8 was and I can imagine a high percentage of users will skip Java 9.