2013-08-15 20 views
6

Stavo leggendo le specifiche JVM per cercare di capire come gestire correttamente i monitor. L'esempio che danno in the relevant section assomiglia a questo:Come si esce correttamente da un monitor in bytecode?

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 

io non riesco a capire il motivo per cui è necessaria la seconda voce della tabella eccezione. Se viene generata un'eccezione da monitorexit, desidero veramente provare ad uscire di nuovo dal monitor? Eventuali eccezioni generate per quanto posso dire sono NullPointerException e IllegalMonitorStateException.

+1

Interessante! C'è un bug Java su di esso, chiuso come "non un problema": http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101 –

risposta

5

C'è un bug Java per questo che è stato chiuso come "Not an issue" - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101. (Complimenti a Tom Anderson per averlo trovato.)

La sezione Valutazione del Bug è davvero illuminante.

Si inizia parlando delle eccezioni "asincrone"; cioè l'eccezione ThreadDeath è così che viene implementato il metodo (deprecato!) Thread.stop(). Il misterioso gestore assicura che il blocco del monitor venga rilasciato anche se il "thread stop" si verifica nel punto critico in cui la JVM sta tentando di rilasciare il blocco.

Quindi Neil Gafter aggiunge che anche l'ipotetico loop infinito (come descritto in questa domanda) è un comportamento corretto in base al JLS. La JLS afferma che il monitor sarà sempre rilasciato prima che il thread continui. Se è impossibile farlo, mettere il thread in un loop infinito è più corretto che fare qualsiasi altra cosa.

+0

+1 Non pensavo a 'Thread.stop()' –

1

Per essere chiari

block 0 : 0 - 3 
block 1 : 4 - 10 
block 2 : 13 - 16/17 
block 3 : 18 

Sono d'accordo che confusa per avere un try/catch sul secondo blocco, perché questo sembra essere un possibile ciclo infinito. Ad esempio, se si verifica un'eccezione tra 13 e 16, salta a 13 per gestirla. Posso solo supporre che sia

  • c'è un'eccezione sicura, riprovabile da cui tenta di proteggersi.
  • viene mantenuto per un oscuro motivo di compatibilità con le versioni precedenti.
  • non c'è una buona ragione per questo ed è un artefatto di come viene generato il codice byte.

Sospetto che non faccia nulla di utile, e immagino che qualcuno in Oracle abbia avuto lo stesso sospetto ma non sapeva per certo che potesse essere rimosso. ;)

+1

Non capisco questa spiegazione. La seconda voce della tabella delle eccezioni copre le righe da 13 a 16 ... non è vero? –

+0

@StephenC Buon punto, spero di averlo chiaro nella mia testa ora. –

+1

infatti è un possibile loop infinito. Ho modificato il file di classe e cambiato monitorenter con istruzioni pop, per causare IllegalMonitorStateException su monitorexit e il programma ha iniziato a pedalare. Ora la domanda è: quale comportamento vogliamo? Possiamo presentare un bug contro il compilatore java. –