10 ms·
JEP Draft: Deprecate memory-access methods in sun.misc.unsafe for removal
- vkaku 3y agoJust days after the 1BRC. Maybe, if the Devs can replicate the perf with VarHandle and MemorySegment, it could go away eventually.
- xonix 3y agoNice. Once I did some experiments at programming in Java using only sun.misc.Unsafe for a memory access: https://github.com/xonixx/gc_less https://github.com/xonixx/gc_less. I was able to implement this way basic data structures (array, array list, hash table). I even explicitely set a very small heap and used Epsilon GC to make sure I don't allocate in heap. Just recently I decided to check if it still works in the latest Java (23) and to my surprise it appears - it is. Now, apparently, this is going to change.
- kaba0 3y agoIt won’t change for many many years to come. It becomes deprecated, which just gives you a warning.
- pjmlp 3y agoSince Java 9, deprecations are actually removed, after a couple of LTS releases.
- kaba0 3y agoA couple of LTS releases is 2*n years, though.
- pjmlp 3y agoThe planned releases for removal are listed on the JEP. If they fail to provide parity, people will do like with modules, keeping holding to older Java versions longer than they should, use the escape command line options if available, turn back to JNI (the opposite this is trying to achieve), or move to other stack if they aren't that dependent on Java, e.g. ongoing Kafka ecosystem evolution.
- slaymaker1907 3y agoI think this is an enormously bad idea. The whole point of using sun.misc.Unsafe is because you need to do something with basically no overhead, regardless of safety. In my opinion, they should just modularize it such that users must enable access to it explicitly. The MemorySegment API is nice, but sometimes you really want to skip bounds checking in a cross platform way.
- throwaway2037 3y agoDid you read the JEP? << Over the past several years, we have introduced two standard APIs that are safe and performant replacements for the memory-access methods in sun.misc.Unsafe: java.lang.invoke.VarHandle, introduced in JDK 9, provides methods to safely and efficiently manipulate on-heap memory: fields of objects, static fields of classes, and elements of arrays. java.lang.foreign.MemorySegment, introduced in JDK 22, provides methods to safely and efficiently access off-heap memory (sometimes in cooperation with VarHandle). These standard APIs guarantee no undefined behavior, promise long-term stability, and have high-quality integration with the tooling and documentation of the Java Platform (examples of their use are given below). Given the availability of these APIs, it is now appropriate to deprecate and eventually remove the memory-access methods in sun.misc.Unsafe. >>
- bremac 3y agoAs the comment you replied to indicates, both of those APIs perform bounds-checking. In certain tight loops, this can add up to quite a bit of overhead [1]. However, it's not documented, but if you really know what you are doing you can convince the JIT to elide the bounds checks for MemorySegments [2]. [1] https://mail.openjdk.org/pipermail/panama-dev/2023-July/019363.html https://mail.openjdk.org/pipermail/panama-dev/2023-July/0193... [2] https://mail.openjdk.org/pipermail/panama-dev/2023-July/019487.html https://mail.openjdk.org/pipermail/panama-dev/2023-July/0194...
- kaba0 3y agoAs pron mentioned, you can use the internal unsafe API without bound checks, you just need a flag for that
- bhakunikaran 3y agoI wonder if a middle ground could be found, perhaps by introducing strict access controls or advanced warnings, instead of complete deprecation.
- vips7L 3y agoMost of sun.misc.Unsafe forwards to jdk.internal, which will still exist and be accessible via --add-exports on the command line. This is a good middle ground for strong encapsulation and making sure users know that they're using internal api's that could change.
- g-b-r 3y agoBounds checking is one of those things that should definitely be performed by the hardware. Is it inherently difficult to do it without performance impacts? Or nobody cared too much for the prevalence of trust-the-developer c thinking? I found some information at https://stackoverflow.com/questions/40752436/do-any-cpus-have-hardware-support-for-bounds-checking https://stackoverflow.com/questions/40752436/do-any-cpus-hav...
- moring 3y agoFirst, please clarify whether you are asking about performance impacts vs. no bounds checking or vs. bounds checking in software. The "vs. no bounds checking" deals with the fact that the bounds must be stored somewhere, so you get an additional memory access, and that's slow (best case, puts some load on the caches). The "vs. software" is more like RISC vs. CISC in general.
- g-b-r 3y ago> First, please clarify whether you are asking about performance impacts vs. no bounds checking or vs. bounds checking in software I was wondering if it would be feasible to have hardware checks with practically no speed difference to performing no check at all. Yes I imagined it could be seen as RISC vs CISC, but it's such a fundamental and frequent operation that it seems likely it would help overall..! Of course you'd need to use registers; which yes means higher cost (unless you already have some for sure never in use at bound-checking times), but there seems to be a good chance it would be worthwhile..? I imagine that the impact of simply reading the additional instructions would be negligible, by the way
- kaba0 3y agoCHERI might allow for that?
- moring 3y agoThe cost is in loading the bounds (e.g. array size) from memory. If you access 100 different arrays, you get 100 load operations for the sizes. A register would only help if you access the same array in a loop, but the majority of loops doesn't need repeated bounds checking anyway: list-map operations, list-reduce operations, System.arraycopy(), whatever -- these only have to check the bounds once before starting the loop. The JVM specifies that every array access gets checked, but since arrays can't change their size, the JIT compiler can move that check outside the loop.
- jeeeb 3y agoThe main sting here seems to be that MemorySegment when allocated from Java code requires bounds checks on all accesses, which the JVM cannot optimise away on random accesses. However, MemorySegment itself already supports unbounded access when wrapping a native pointer. It’s necessary for even basic interactions with native code (e.g. reading a c-str). It should be easy to “wash” an off-heap MemorySegment through native code to obtain an unbounded MemorySegment from it. Something like: void *vanish_bounds(void *ptr) { return ptr; } I think it would be nice if the FFI provided a way to get an unbounded MemorySegment without resorting to native code hacks though. It can obviously be made restricted like unbounded MemorySegment’s already are. That should take most of the sting out of this proposal (although it still sounds like a painful transition for a very modest gain).