PDA

View Full Version : JAVA: eccezioni ingestibili


Molz
28-05-2004, 11:01
Ho costruito un JFrame con Java che contiene al suo interno, tra le altre cose, un JTree.

Siccome devo aggiornare periodicamente la visualizzazione di questo frame ho costruito un apposito Thread con questo codice


class Refresher extends Thread{
TopicNameSpaceFrame ilFrameDaAggiornare;

public Refresher(TopicNameSpaceFrame a){ilFrameDaAggiornare=a;}

public void run(){
this.setPriority(Thread.MIN_PRIORITY);
try{
while(true){
Thread.sleep(1000 * 10);
/*codice vario*/
ilFrameDaAggiornare.jTree.updateUI();
}
}catch(Exception e){/* qui non entra */}
}



Il codice fa quello che deve fare, solo che, puntualmente ogni 10 secondi (solo se il frame è visibile e solo se la riga in grassetto è presente nel codice) mi lancia una NullPointerException ke nn riesco a gestire e guardando lo stackTrace(ke ora nn posso postare :( ) vedo ke l'eccezione occorre solo in classi presenti in java.awt e in javax.swing e in nessuna classe del mio package.

Come faccio a gestirla o a evitarla?

kingv
28-05-2004, 11:32
non capisco, anche se NullPointerException discende da RuntimeException il catch dovrebbe intercettarla.

Sei sicuro arrivi dal codice dentro il try?

Molz
28-05-2004, 11:42
Si si.

Come dicevo le eccezioni nn occorrono nel mio codice ma solo nelle classi di java.awt e di javax.swing
Se riesco posto lo stack trace dell'eccezione.

Molz
28-05-2004, 11:47
Eccolo

java.lang.NullPointerException
at javax.swing.plaf.basic.BasicTreeUI.paint(Unknown Source)
at javax.swing.plaf.metal.MetalTreeUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)
at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

io nn so proprio ke fare...

kingv
28-05-2004, 12:02
non riesci a farne il catch allora perchè e' in un thread diverso.

perche' chiami updateUI? e' proprio necessario?
generalmente il chiamarlo espressamente incica qualche problema col model sottostante.

Molz
28-05-2004, 12:10
Se nn kiamo updateUI nn visualizzo i cambiamenti del JTree.

Le varie repaint update di Graphic nn danno nessun effetto

Cmq il Thread diverso dove nasce l'eccezione, da qello ke ho capito, lo fa Java con le sue API

cn73
28-05-2004, 13:48
Prova così:




while(true){
Thread.sleep(1000 * 10);
/*codice vario*/
try{
ilFrameDaAggiornare.jTree.updateUI();
}catch(Exception e){/* qui non entra */}
}

Molz
31-05-2004, 11:42
Ok proverò, domani t saprò dire (prima nn posso), cmq anke la sleep va in 1 blocco try-catch.

Xkè dovrebbe cambiare qalcosa?

cn73
31-05-2004, 13:16
Bhè innanzitutto è più corretto... quel while (true) indica che vuoi ripetere all'"infinito" il codice, il fallimento di una sleep o di un'updateUI non deve pregiuducare le successive esecuzioni... E poi... bhè, quando incontro un problema assurdo, rispondo con una soluzione ancora più assurda, magari mi va bene ;)

Molz
01-06-2004, 11:21
La soluzione nn era abbastanza assurda! Il problema è rimasto. Vabbè visto ke cmq l'esecuzione nn mi da problemi penso ke risolverò il problema così:

java mioPackage.mioMain 2> /dev/null

Okkio nn vede, cuore nn duole :D

PGI
01-06-2004, 12:10
Non credo sia la soluzione al problema perchè quanto scrivo evita problemi di dead-lock dovuti all'istruzione di aggiornamento grafico "arrembante". Ma non si sa mai.


while(true){
Thread.sleep(1000 * 10);
/*codice vario*/
ilFrameDaAggiornare.jTree.updateUI();
}


Questo pezzo è ad alto rischio. Tutte le istruzioni di aggiornamento grafico di un componente Swing devono essere delegate all'unico thread EventDispatcher.

La delega è realizzata in tutti i gestori di evento AWT: nell'esecuzione comune di un interfaccia grafica pertanto non c'è nulla da aggiungere (premo un bottone, il controllo passa ad un actionListener, nell'actionListener aggiorno un componente e tutto fila liscio, perchè ActionListener è "swing-safe". Vale per tutti i listener AWT).

Quando Thread diversi da EventDispatcher contribuiscono all'aggiornamento di un componente Swing entrano in gioco i metodi SwingUtilities.invokeLater(Runnable) e SwingUtilities.invokeAndWait(Runnable).

Quello che i metodi citati fanno è accodare le istruzioni contenute nel metodo "run()" del Runnable in argomento all'EventDispatcher.

Il primo accoda l'evento e restituisce immediatamente il controllo al chiamante, il secondo attende che l'esecuzione del "run()" sia completata (ecco perchè questo non può essere chiamato all'interno dell'EventDispatcher: attenderebbe sè stesso).

Forma corretta:


while(true){
Thread.sleep(1000 * 10);
/*codice vario*/
Runnable updater = new Runnable() {
public void run() {
ilFrameDaAggiornare.jTree.updateUI();
}
}
SwingUtilities.invokeLater(updater);
}


ilFrameDaAggiornare deve diventare "final". Normalmente è fattibile senza modifiche al codice salvo l'aggiunta di un "final" alla dichiarazione.

Ciao.

[update]
ho corretto qualche strafalcione di grammatica

Molz
01-06-2004, 12:21
Grazie mille.
Nn so se funzionerà, ma almeno adesso ne so d + su qello ke sto facendo.

Domani t saprò dire. Ciao

cn73
01-06-2004, 14:50
PGI, come al solito, ha ragione... Dai un'occhiata anche alla classe SwingWorker.

Per levarti la soddisfazione di capire il tipo di errore, catcha, invece che Exception, Throwable che è il papà di tutti gli errori. Anche la classe Throwable ha il metodo printSTackTrace()...

cn73
03-06-2004, 08:49
E quindi?

Molz
03-06-2004, 13:39
La soluzione d PGI funziona.

Invece catchando Throwable nn cambia niente, infatti l'errore era 1 NullPointerException e veniva generata in 1 altro Thread e qindi nn riuscivo a gestirla lì.

Grazie mille a tutti