我正在阅读JVM规范,试图弄清楚如何正确处理监视器。他们在the relevant section中提供的示例如下所示:
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
我无法弄清楚为什么需要第二个异常表条目。如果monitorexit
抛出异常,我真的想再次尝试退出监视器吗?
据我所知,可能的例外情况是NullPointerException
和IllegalMonitorStateException
。
答案 0 :(得分: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表示在线程继续之前将始终释放监视器。如果不可能这样做,那么将线程置于无限循环中比执行任何其他操作更正确。
答案 1 :(得分:1)
要清楚
block 0 : 0 - 3
block 1 : 4 - 10
block 2 : 13 - 16/17
block 3 : 18
我同意在第二个块上有一个try / catch是令人困惑的,因为这似乎是一个可能的无限循环。即如果在13和16之间发生异常,则跳转到13以处理它。我只能假设
我怀疑它没有做任何有用的事情,我想在甲骨文的某个人有同样的怀疑,但不确定它可以被删除。 ;)