为什么有JVM指令`monitorenter / monitorexit`但没有`wait / notifyAll`(它们是本机调用)?

时间:2015-01-12 08:56:50

标签: java bytecode language-design

当我们编写synchronized(some_object){}时,我们可以看到两个JVM指令monitorenter/monitorexit作为字节代码发出。

当我们写synchronized(some_object){some_object.wait()}时,我希望看到像wait这样的特殊JVM指令,但是没有 - 而wait/notify被实现为本机C函数。

为什么存在这样的不一致(要么将它们全部作为JNI还是作为java字节代码)?是否存在特定(历史)原因或仅仅是品味问题?

上下文:我对此感兴趣,因为字节码中包含所有monitorenter/monitorexit/wait/notify将允许JavaByteCode程序正确性验证程序无法处理JNI'验证不使用JNI的并发Java程序。目前,这种假设工具必须解决等待/通知问题。

2 个答案:

答案 0 :(得分:6)

  

我希望看到像wait

这样的特殊JVM指令

我不会。这在我看来是不一致的 - 在源代码中,你只是调用一个方法,所以你只是在字节码中调用一个方法也是有意义的。否则,编译器必须具备这些方法的特殊知识,而目前还不具备这些方法。

可以说,monitorentermonitorexit通过方法调用实现更有意义(例如,在.NET中)。某些方法总是本机的并且与JVM本身密切相关 - 我没有看到任何不合理的东西,我不希望每个方法都通过单独的字节码操作来实现。但是,由于synchronized具有支持它的特殊字节码,我没有太多很多问题,因为它是一种语言结构(如try/catch/finally),而不仅仅是常规方法调用

答案 1 :(得分:4)

由于waitnotify调用的语义已明确指定,因此无需验证程序来处理JNI。这与专用字节码指令没有什么不同。这同样适用于热点优化器如何处理许多众所周知的方法调用,其中可能包括waitnotify。它不一定会生成昂贵的JNI调用,而是生成直接执行这些低级操作的代码。以这种方式处理的方法称为intrinsic methods(另请参阅herehere

如果您尝试为每个代码保留操作码,那么您就不能再将其称为字节代码了。此外,以这种方式处理哪些方法取决于实际的JVM实现以及它运行的硬件体系结构。它也可能在不同版本之间发生变化,因此通过为它们定义字节码指令没有任何意义可以将它刻画成石头。

您写道“目前,此类假设工具必须解决等待/通知”。事实上,处理这些特殊方法并非一种解决方法。正是这样的审计工具与许多方法有关,比如LockCondition中声明的那些具有类似线程相关语义的方法,但现在还有很多其他众所周知的并发工具必须处理。

创建monitorentermonitorexit说明但在wait上制作notifyObject方法的确切决定是历史性的(可追溯到20多年前) )。今天,如果开发者不得不重新做出决定,那么决定可能会有所不同。但我想它更倾向于使偶数monitorentermonitorexit在引擎盖下调用的特殊方法而不是字节码指令。首先,它们不再是唯一的线程同步工具。其次,它是大多数新功能在最近的JVM中添加的方式,最好是作为方法,即使它预计会被大多数(如果不是全部)实现所吸引。