如何正确退出字节码中的监视器?

use*_*171 6 java bytecode synchronized synchronized-block

我正在阅读JVM规范,试图找出如何正确处理监视器.他们在相关部分中给出的示例如下所示:

0   aload_1             // Push f
1   dup                 // Duplicate it on the stack
2   astore_2            // Store duplicate in local variable 2
3   monitorenter        // Enter the monitor associated with f
4   aload_0             // Holding the monitor, pass this and...
5   invokevirtual #5    // ...call Example.doSomething()V
8   aload_2             // Push local variable 2 (f)
9   monitorexit         // Exit the monitor associated with f
10  goto 18             // Complete the method normally
13  astore_3            // In case of any throw, end up here
14  aload_2             // Push local variable 2 (f)
15  monitorexit         // Be sure to exit the monitor!
16  aload_3             // Push thrown value...
17  athrow              // ...and rethrow value to the invoker
18  return              // Return in the normal case
Exception table:
From    To      Target      Type
4       10      13          any
13      16      13          any
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么需要第二个异常表条目.如果抛出异常,monitorexit我真的想再次尝试退出监视器吗?据我所知,抛出的可能异常是NullPointerExceptionIllegalMonitorStateException.

Ste*_*n C 5

有一个Java Bug已被关闭为"不是问题" - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101.(感谢Tom Anderson找到它.)

Bug的评估部分真的很有启发性.

它首先讨论处理"异步"异常; 即ThreadDeath异常,即(已弃用!)Thread.stop()方法的实现方式.神秘的处理程序确保即使在JVM试图释放锁定的关键点发生"线程停止",也会释放监视器锁定.

然后Neil Gafter补充说,根据JLS,即使是假设的无限循环(如本课题中所述)也是正确的行为.JLS表示在线程继续之前将始终释放监视器.如果不可能这样做,那么将线程置于无限循环中比执行任何其他操作更正确.