1

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.

Ayrat
  • 1,221
  • 1
  • 18
  • 36
  • 1
    Why not? Purely opinion-based, unless you can get Jim Gosling on the wire. – user207421 Jan 12 '15 at 09:15
  • I don't know about Jim but James Gosling would probably agree with Jon Skeet. One is defined as a method and uses method bytecode, the other a language construct that has it's own special bytecode. Both are probably implemented in native code. But that's up to the JVM. – zapl Jan 12 '15 at 09:34

2 Answers2

6

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

There is no need for a verification program to deal with JNI as the semantics of wait and notify calls are well-specified. That’s not different to dedicated bytecode instructions. The same applies to how the hot spot optimizer deals with a lot of well known method invocations, which may include wait and notify. It does not necessarily generate a costly JNI invocation but rather generate code performing these low-level operations directly. Methods handled this way are called intrinsic methods (see also here or here.

There are so many, that you couldn’t call it bytecode anymore if you tried to reserve an opcode for each of them. Further, which methods are handled this way, depends on the actual JVM implementation and the hardware architecture on which it runs. It might also change between versions so there is no sense to carve it in stone by defining bytecode instructions for them.

You wrote “Currently, such hypothetical tool has to workaround wait/notify”. In fact, handling these special methods is not a work-around. It’s what such an audit tool has to do with a lot of methods like these declared in Lock and Condition which have similar threading-related semantics but there are also a lot of other well-known concurrency tools nowadays which have to be handled.

The exact decision to create monitorenter and monitorexit instructions but make wait and notify methods on Object is historical (it dates back over 20 years ago). Today, the decision might look different if the developers had to make it again. But I guess it would rather go into the direction to make even monitorenter and monitorexit special methods that are invoked under the hood rather than bytecode instructions. First, they are not the only thread synchronization tool anymore. Second, it’s how most of the new feature were added in the recent JVMs, preferably as method, even if it’s expected to be intrinsified by most, if not all, implementations.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • this answers the question! Indeed, instead of calling such JNI function the tool could simply assume the 'right' semantics of such methods (looks like semantics of intrinsics are clearly defined). Aside note: What do you mean by "they are not the only thread synchronization tool anymore" -- `monitorenter` is used for other than thread synch purposes? for which? – Ayrat Jan 12 '15 at 16:06
  • 1
    No, it means there are other tools for thread synchronization. Most notably, you can do the same with [`ReentrantLock`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) and `Condition` whereas the bytecode will consist of only method invocations then. So `synchronized` has a different syntax on source code level but fulfills the same purpose. So it’s debatable whether it shall have its own bytecode instruction… – Holger Jan 12 '15 at 16:25