clojure 2025-10-29

Hi. Catching up on JEP 491. Can anyone tell me if Clojure's locking macro (monitorenter/monitorexit bytecodes 194/195) benefits from JEP 491, or does JEP 491 only apply to Java's synchronized keyword specifically? (I'm not sure whether JVM fixes like this apply at the bytecode level or only to specific language constructs.)

It is the same bytecode

Java's synchronized is compiled to call to monitorenter and monitorexit

In theory they could change how synchronized blocks are compiled to something else, but that would be very problematic because java allows for separate compilation, and mixing stuff compiled with a new compiler and an old one could result in bad things (disagreement about if a lock is held, etc)

The purpose of the change is to remove extra pinning from the breadth of libraries in the wild, and it would have to work over libraries shipped as compiled bytecode

Makes a lot of sense when you put it this way indeed.

I think this is the clearest explanation I've seen: > The synchronized keyword relies on monitors associated with objects. Until Java 24, when a virtual thread acquired the monitor via synchronized, the JVM perceived the carrier platform thread as the one holding it. Since virtual threads could be moved between platform threads, pinning was necessary to ensure that only one thread/virtual thread could acquire the monitor at a time. > Since Java 24, “virtual threads can acquire, hold, and release monitors, independently of their carriers”. This means that synchronized should no longer cause thread pinning. This is a significant win for the whole Java community, as the synchronized is still widely used in various codebases. https://mikemybytes.com/2025/04/09/java24-thread-pinning-revisited/

We had already done profiling and fixed most of our pinning problems by changing our code and other libraries around (eg avoiding sync apache http) before we attempted to upgrade to java 24, so we didn't really notice anything. Java flight recorder can tell you.

I get that I was only unsure about the change affecting java's synchronized only or the underlying bytecode opcodes (interpretation or whatever). Seems like it is the latter which is indeed better for the whole ecosystem.

It's quite amazing to me, I think I asked myself whenever JS got async/await 'why can't everything just be async?' and I guess it took that long for someone to do it.

🎯 1

Another thing like that is ocaml eio, which is also pretty new https://github.com/ocaml-multicore/eio