Why there are JVM instructions `monitorenter/monitorexit` but no `wait/notifyAll` (they are native calls)?

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.

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow