为什么调用方法的Java字节码会隐式获取和释放监视器?
I've been reading up on the Java Virtual Machine Instruction Set and noticed that when using instructions to invoke methods (e.g. invokestatic, invokevirtual, etc.) that are marked synchronized, it's up to that particular bytecode instruction to acquire the monitor on the receiver object. Similarly, when returning from a method, it's up to the instruction that leaves the method to release the monitor when the method is synchronized. This seems strange, given that there are explicit monitorenter and monitorexit bytecodes for managing monitors. Is there a particular reason for the JVM designing these instructions this way, rather than just compiling the methods to include the monitorenter and monitorexit instructions where appropriate?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
早在 90 年代中期,还没有 Java JIT 编译器,微同步被认为是一个非常好的主意。
因此,您经常调用这些同步方法。甚至
Vector
也有它们!您无需解释额外的字节码即可处理。但不仅仅是在代码运行时。类文件更大。额外的说明,还设置了
try
/finally
表并验证是否有一些顽皮的东西没有被插入。只是我的猜测。
Back in the mid-90s, there were no Java JIT compilers and micro-synchronisation was thought to be a really great idea.
So you are calling these synchronised method a lot. Even
Vector
has 'em! You could deal without the extra bytecodes to interpret.But not just when the code is being run. The class file is bigger. Extra instructions, but also setting up the
try
/finally
tables and verification that something naughty hasn't been slipped in.Just my guess.
你问为什么有两种方法做同样的事情?
当一个方法与市场同步时,再有监视器进入/退出指令将是多余的。如果它只有monitorenter/exit指令,您将无法从外部看到该方法是同步的(无需阅读实际代码)。
有多个示例说明了两种或多种方法可以完成同一件事。每个都有相对的优点和缺点。 (例如,许多单字节指令是两字节指令的简短版本)
编辑:我必须在问题中遗漏一些东西,因为调用者不需要知道被调用者是否同步
产生代码
Are you asking why are there two ways of doing the same thing?
When a method is market as synchronized, it would be redundant to also have monitorenter/exit instructions. If it only had monitorenter/exit instruction you would not bet able to see externally that the method is synchronized (without reading the actual code)
There are more than a few examples of two or more ways of doing the same thing. Each has relative strengths and weaknesses. (e.g. many of the single byte instructions are short versions of a two byte instruction)
EDIT: I must be missing something in the question because the caller doesn't need to know if the callee is synchronized
produces the code
通过将锁管理委托给调用者,现在可以进行一些优化。例如,假设您有一个如下所示的类:
并假设该调用者类使用它:
根据转义分析,JVM 知道
foo
永远不会转义线程。正因为如此,它可以避免隐式的MONITORENTER
和MONITOREXIT
指令。在 JVM 的早期,当速度是一种稀有商品时,避免不必要的锁可能更受性能驱动。
<speculation>
By delegating lock management onto the caller, some optimizations are now possible. For example, suppose you have a class like this:
And suppose it is used by this caller class:
Based on escape analysis, the JVM knows that
foo
never escapes the thread. Because of this, it can avoid the implicitMONITORENTER
andMONITOREXIT
instructions.Avoiding unnecessary locks may have been more performance-driven in earlier days of the JVM when speed was a rare commodity.
</speculation>
您是否在问为什么同步方法使用显式监视器进入和退出指令,而 JVM 可以通过查看方法的属性来推断它们?
我猜这是因为,除了方法之外,还可以同步任意代码块:
因此,对同步方法和同步块使用相同的指令是有意义的。
Are you asking why synchronised methods use explicit monitor entry and exit instruction when the JVM could infer them by looking at the method's attributes?
I would guess it is because, as well as methods it is possible to synchronise arbitrary blocks of code:
Therefore it makes sense to use the same instructions for both synchronised methods and synchronised blocks.
正在搜索同一个问题,并发现了以下文章。看起来方法级同步生成的字节代码比块级同步稍微高效一些。对于块级同步,会生成显式字节代码来处理方法级同步未完成的异常。因此,一个可能的答案可能是,这两种方法用于使方法级同步稍微快一些。
http://www.ibm.com/developerworks/ibm/library/it- haggar_bytecode/
Was searching on the same question, and came across the following article. Looks like method level synchronization generates slightly more efficient byte code than block level synchronization. For block level synchronization, explicit byte code is generated to handle exceptions which is not done for method level synchronization. So a possible answer could be, these two ways are used to make method level synchronization slightly faster.
http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/