2015-04-14 19 views
15

Ho un programma Java che prende il 100% della CPU, ma apparentemente non fa nulla.Ciclo infinito in EventQueue.isDispatchThread()

Se prendo un dump di thread, ci sono 4 thread (fuori da un pool di 5) in attesa di prendere un blocco.

"Incoming WorkPool 5" - Thread [email protected] 
    java.lang.Thread.State: WAITING 
    at sun.misc.Unsafe.park(Native Method) 
    - waiting to lock <7212149b> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) owned by "Incoming WorkPool 3" [email protected] 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197) 
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214) 
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290) 
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1019) 
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014) 

Il filo che stanno per è RUNNABLE

"Incoming WorkPool 3" - Thread [email protected] 
    java.lang.Thread.State: RUNNABLE 
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1024) 
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014) 

Questo è JDK 7.0.25, così sembra un thread è bloccato sul

EventQueue next = eq.nextQueue; 
while (next != null) { 
    eq = next; 
    next = eq.nextQueue; 
} 

Ci sono due fili AWT EventQueue , cercando di acquisire lo stesso pushpoplock.

La VM funziona come un servizio, quindi non dovrebbe provare a fare cose AWT, ma è fatto da una libreria che sto usando.

Qualche idea? Posso impedire che ciò accada?

Grazie!

+0

1. hai sentito parlare di SecondaryLoop, 2. ma "prendere il 100% della CPU, ma apparentemente non fare nulla". parlando di JProfiler, 3. senza SSCCE/MCVE non è possibile rispondere, 4. 'java.awt.EventQueue.isDispatchThreadImpl (EventQueue.java: 1019) parlando di isEventDispatchThread restituisce false', o gli eventi eseguiti in EDT non hanno business lì 5. nessuna idea, senza eventi da EDT corrente o eccezione da RepaintManager – mKorbel

+0

1) Non avevo sentito parlare di SecondaryLoop prima. L'ho cercato ma io stesso non uso AWT, è una libreria che uso che chiama il metodo. 2) Non ho usato JProfiler, ho usato JVisualVM, mi ha fornito il threaddump che ho mostrato snippet di. 3) Non posso riprodurlo sfortunatamente. Era un problema che avevo in produzione, tutto quello che ho è il dump del thread, quindi non posso fornire un SSCCE. 4-5) Temo di non capirli. –

+1

Chi sta impostando eq.nextQueue su null? Se nessuno lo imposta, il ciclo verrà eseguito all'infinito e CPU 100% è possibile. Se sì e se fatto da qualche altro thread, sq.nextQueue dovrebbe essere volatile. In caso contrario, questo thread potrebbe non selezionare il valore poiché il thread può contenere nella cache il valore di eq.nextQueue, in cui il ciclo verrà eseguito di nuovo all'infinito e CPU al 100% possibile. – Eranda

risposta

0

Il problema è un problema di stallo (see wikipeida).

Deadlock situation here Come potete vedere sopra, i tuoi due EventQueues (qui R1 e R2) si trovano in una situazione di stallo - ognuno di loro ha sostenuto una risorsa e non può essere eseguito ulteriormente mentre l'altro ha sostenuto l'altra risorsa. Entrambi si stanno aspettando l'un l'altro senza fine.

È possibile risolvere questo problema con diversi approcci:

provare a cambiare la libreria, hai ragione che una libreria non dovrebbe cercare di fare AWT roba se non è una libreria strettamente legato al AWT. Esistono molte librerie su piattaforme come github, sono abbastanza sicuro che trovi un'altra libreria per sostituire quella che causa l'errore.

Se si è in grado di modificare il codice per aggiungere il monitoraggio si è prevenendo anche eventuali deadlock.

synchronized(lock){ 
EventQueue next = eq.nextQueue; 
while (next != null) { 
    eq = next; 
    next = eq.nextQueue; 
} 
lock.notifyAll(); 
} 
+0

Il codice sopra fa parte dell'SDK Java (java.awt.EventQueue.isDispatchThreadImpl (EventQueue.java:1024)), non è possibile in alcun modo che io possa modificare il codice. –

1

C'è qualche possibilità che push(EventQueue newEventQueue) viene chiamato dal programma di applicazione e che spinge lo stesso EventQueue? Se sì, quindi, this e il suo nextQueue saranno gli stessi oggetti e verranno eseguiti in un ciclo infinito che consuma CPU al 100%.

Dalla traccia stack è evidente che almeno un thread è in esecuzione. Quindi non è una questione di DEADLOCK.

Dal suggerimento del consumo della CPU al 100% e dal suo stato RUNNABLE, è evidente che sta eseguendo un ciclo infinito.

Il codice può andare in ciclo infinito se e solo se ilnextQueue ha un valore che è già nella catena (o this). Potrebbe benissimo essere un problema applicativo. Grazie.

+0

Non ci ho mai pensato, ma è effettivamente possibile che la libreria che uso faccia questo EventQueue.push. Non è una libreria open source, quindi dovrò verificare con loro. –