When we write synchronized(some_object){}
we can see two JVM instructions monitorenter/monitorexit
issued as the byte code.
When we write synchronized(some_object){some_object.wait()}
i would expect to see special JVM instructions like wait
, but none -- instead wait/notify
are implemented as native C functions.
Why there is such inconsistency (either have them all as JNI or as java byte code)? Was there a particular (historical) reason or it is just a matter of taste?
Context: i am interested in this because having all monitorenter/monitorexit/wait/notify
in the bytecode would allow 'JavaByteCode program correctness verifiers that do not handle JNI' to verify concurrent Java programs that do not use JNI. Currently, such hypothetical tool has to workaround wait/notify.
i would expect to see special JVM instructions like
wait
I wouldn't. That would be inconsistent, in my view - in the source code, you're just calling a method, so it makes sense that you're just calling a method in the bytecode as well. Otherwise the compiler would have to have special knowledge of those methods, where it doesn't at the moment.
Arguably it would make more sense for monitorenter
and monitorexit
to be implemented via method calls as well (as they are in .NET, for example). Certain methods will always be native and deeply tied to the JVM itself - I don't see anything unreasonable about that, and I wouldn't want each of those to be implemented via a separate bytecode operation. However, I don't have too much issue with synchronized
having special bytecode supporting it, given that it's a language construct (like try/catch/finally
) rather than just a regular method call.
See more on this question at Stackoverflow