2010-06-11 4 views
11

(il codice di esempio riportato di seguito è a sé stante e eseguibile, si può provare, che non vada in crash il sistema :)L'EDT si riavvia o no quando viene generata un'eccezione?

Tom Hawtin ha commentato sulla questione qui: Why do people run Java GUI's on the Event Queue

che:

È improbabile che l'EDT si blocchi. Le eccezioni non controllate generate nel messaggio EDT vengono catturate, scaricate e il thread continua.

Qualcuno mi può spiegare cosa sta succedendo qui (ogni volta che si fa clic sul "un'eccezione unchecked" pulsante, viene eseguita una divisione per zero, apposta):

import javax.swing.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 

public class CrashEDT extends JFrame { 

    public static void main(String[] args) { 
     final CrashEDT frame = new CrashEDT(); 
     frame.addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }); 
     final JButton jb = new JButton("throw an unchecked exception"); 
     jb.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("Thread ID:" + Thread.currentThread().getId()); 
       System.out.println(0/Math.abs(0)); 
      } 
     }); 
     frame.add(jb); 
     frame.setSize(300, 150); 
     frame.setVisible(true); 
    } 

} 

I il seguente messaggio (che è quello che ci si aspetta):

Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException:/by zero 

e per me questa è un'eccezione incontrollato giusto?

È possibile notare che l'ID del thread viene incrementato ogni volta che si attiva l'arresto anomalo.

Quindi l'EDT viene riavviato automaticamente ogni volta che viene emessa un'eccezione non controllata o sono le eccezioni non selezionate "rilevato, scaricato e il thread continua" come ha commentato Tom Hawtin?

Cosa sta succedendo qui?

+1

Un'interessante nota a margine su una questione completamente diversa: non è necessario eseguire Math.abs (0) per "ingannare" il compilatore per accettarlo. 0/0 è un'espressione ok e genererà anche l'eccezione. [leggi di più ...] (http: // StackOverflow.it/questions/2934063/is-1-0-a-legal-java-expression) – aioobe

+0

@aioobe: lui lui, lo so, lo so, ho letto quella discussione ... Ma se avesse scritto 0/0 o 1/0 allora la gente avrebbe chiesto che quella cosa fosse anche compilando :) – NoozNooz42

+0

hahaha ... buon punto :-) – aioobe

risposta

4

Per riferimento, "La particolare comportamento dei this machinery è implementazione-dipendente." Ad esempio, l'ID del thread rimane invariato sulla mia piattaforma. L'effetto netto, discusso in AWT Threading Issues, è che "la JVM non uscirà mentre c'è almeno un componente visualizzabile".

+0

@trashgod: l'ho provato solo su un sistema Debian Linux finora +1, e che http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues. il collegamento html è roba eccellente! – NoozNooz42

+0

sì. Sono su ubuntu usando java 6. quale sistema sei su trashgod? – aioobe

+0

@ NoozNooz42: Mentre Mac OS X mantiene lo stesso ID, vedo l'incremento che si riferisce su Ubuntu 10.04. – trashgod

5

Interessante domanda. Avrei pensato che le eccezioni sono state prese e che il thread è andato avanti, ma dopo alcune ricerche non ne sono così sicuro.

Ho esteso il programma con un

Set<Thread> seenAwtThreads = new HashSet<Thread>(); 

in cui ho raccolto tutti "visto" le discussioni AWT, e la dimensione del set aumenta ogni volta che clicco sul "eccezione tiro" -per, che sembra suggerire che un nuovo thread è inizializzato in caso di un'eccezione.

finalmente ho trovato questo commento nel run realizzazione di EventDispatchThread:

/* 
* Event dispatch thread dies in case of an uncaught exception. 
* A new event dispatch thread for this queue will be started 
* only if a new event is posted to it. In case if no more 
* events are posted after this thread died all events that 
* currently are in the queue will never be dispatched. 
*/ 

L'implementazione del metodo run completa assomiglia:

public void run() { 
    try { 
     pumpEvents(new Conditional() { 
      public boolean evaluate() { 
       return true; 
      } 
     });  
    } finally { 
     /* 
     * This synchronized block is to secure that the event dispatch 
     * thread won't die in the middle of posting a new event to the 
     * associated event queue. It is important because we notify 
     * that the event dispatch thread is busy after posting a new event 
     * to its queue, so the EventQueue.dispatchThread reference must 
     * be valid at that point. 
     */ 
     synchronized (theQueue) { 
      if (theQueue.getDispatchThread() == this) { 
       theQueue.detachDispatchThread(); 
      } 
      /* 
      * Event dispatch thread dies in case of an uncaught exception. 
      * A new event dispatch thread for this queue will be started 
      * only if a new event is posted to it. In case if no more 
      * events are posted after this thread died all events that 
      * currently are in the queue will never be dispatched. 
      */ 
      /* 
      * Fix for 4648733. Check both the associated java event 
      * queue and the PostEventQueue. 
      */ 
      if (theQueue.peekEvent() != null || 
       !SunToolkit.isPostEventQueueEmpty()) { 
       theQueue.initDispatchThread(); 
      } 
      AWTAutoShutdown.getInstance().notifyThreadFree(this); 
     } 
    } 
} 
+0

+1, questo è interessante. Quel codice è da Java 7? – NoozNooz42

+0

@ NoozNooz42, no, penso che sia 6. Fammi sapere se scopri che è cambiato in java 7 :-) – aioobe

+0

Ci scusiamo per la risposta ritardata. Ho usato Java 1.6 sia su Mac OS X 10.5.8 che su Ubuntu 10.04. La sorgente Mac è identica a quella mostrata da te. – trashgod

0

C'è un valore predefinito UncaughtExceptionHandler impostato sul thread di invio eventi, che stampa l'eccezione su System.out e quindi continua nella discussione.