2011-11-08 21 views
11

Ho un problema intermittente su un server di build in cui un processo Java nella build non riesce in qualche modo a terminare e sembra continuare a funzionare (usando il 100% della CPU) per sempre (l'ho visto funzionare per 2+ giorni durante il fine settimana dove normalmente ci vogliono circa 10 minuti). kill -9 pid sembra essere l'unico modo per interrompere il processo.Perché questo processo Java non riesce a terminare?

Ho provato a chiamare kill -QUIT pid sul processo, ma non sembra produrre alcuna traccia di stack su STDOUT (forse non risponde al segnale?). jstack senza l'opzione -F force sembra non essere in grado di connettersi alla JVM in esecuzione, ma con l'opzione force produce l'output incluso di seguito.

Sfortunatamente, anche con quella traccia di stack non riesco a vedere alcun percorso ovvio per ulteriori indagini.

Per quanto ne so, mostra due thread "BLOCCATI" che hanno eseguito Object.wait (i loro stack sembrano contenere solo il codice Java principale, niente dei nostri) e un terzo che è "IN_VM" senza uscita stack .

Quali passi devo prendere per raccogliere maggiori informazioni sulla causa del problema (o meglio ancora, come posso risolverlo)?

 
$ /opt/jdk1.6.0_29/bin/jstack -l -F 5546 
Attaching to process ID 5546, please wait... 
Debugger attached successfully. 
Server compiler detected. 
JVM version is 20.4-b02 
Deadlock Detection: 

No deadlocks found. 

Finding object size using Printezis bits and skipping over... 
Thread 5555: (state = BLOCKED) 

Locked ownable synchronizers: 
    - None 

Thread 5554: (state = BLOCKED) 
- java.lang.Object.wait(long) @bci=0 (Interpreted frame) 
- java.lang.ref.ReferenceQueue.remove(long) @bci=44, line=118 (Interpreted frame) 
- java.lang.ref.ReferenceQueue.remove() @bci=2, line=134 (Interpreted frame) 
- java.lang.ref.Finalizer$FinalizerThread.run() @bci=3, line=159 (Interpreted frame) 

Locked ownable synchronizers: 
    - None 

Thread 5553: (state = BLOCKED) 
- java.lang.Object.wait(long) @bci=0 (Interpreted frame) 
- java.lang.Object.wait() @bci=2, line=485 (Interpreted frame) 
- java.lang.ref.Reference$ReferenceHandler.run() @bci=46, line=116 (Interpreted frame) 

Locked ownable synchronizers: 
    - None 

Thread 5548: (state = IN_VM) 

Locked ownable synchronizers: 
    - None 

(versione Java 1.6.0 update 29, in esecuzione su Scientific Linux rilascia 6,0)

Aggiornamento:

Esecuzione strace -f -p 894 produce un flusso apparentemente infinito di ...

[pid 900] sched_yield()    = 0 
[pid 900] sched_yield()    = 0 
... 

e quindi quando Ctrl-Cd

Process 894 detached 
... 
Process 900 detached 
... 
Process 909 detached 

jmap -histo 894 non di connessione, ma jmap -F -histo 894 ritorna ...

 
Attaching to process ID 894, please wait... 
Debugger attached successfully. 
Server compiler detected. 
JVM version is 20.4-b02 
Iterating over heap. This may take a while... 
Finding object size using Printezis bits and skipping over... 
Finding object size using Printezis bits and skipping over... 
Object Histogram: 

num  #instances #bytes Class description 
-------------------------------------------------------------------------- 
1:  11356 1551744 * MethodKlass 
2:  11356 1435944 * ConstMethodKlass 
3:  914 973488 * ConstantPoolKlass 
4:  6717 849032 char[] 
5:  16987 820072 * SymbolKlass 
6:  2305 686048 byte[] 
7:  914 672792 * InstanceKlassKlass 
8:  857 650312 * ConstantPoolCacheKlass 
9:  5243 167776 java.lang.String 
10:  1046 108784 java.lang.Class 
11:  1400 87576 short[] 
12:  1556 84040 * System ObjArray 
13:  1037 64584 int[] 
14:  103 60152 * ObjArrayKlassKlass 
15:  622 54736 java.lang.reflect.Method 
16:  1102 49760 java.lang.Object[] 
17:  937 37480 java.util.TreeMap$Entry 
18:  332 27960 java.util.HashMap$Entry[] 
19:  579 27792 java.nio.HeapByteBuffer 
20:  578 27744 java.nio.HeapCharBuffer 
21:  1021 24504 java.lang.StringBuilder 
22:  1158 24176 java.lang.Class[] 
23:  721 23072 java.util.HashMap$Entry 
24:  434 20832 java.util.TreeMap 
25:  689 18936 java.lang.String[] 
26:  238 17440 java.lang.reflect.Method[] 
27:  29 16800 * MethodDataKlass 
28:  204 14688 java.lang.reflect.Field 
29:  330 13200 java.util.LinkedHashMap$Entry 
30:  264 12672 java.util.HashMap 
... 
585:  1 16 java.util.LinkedHashSet 
586:  1 16 sun.rmi.runtime.NewThreadAction$2 
587:  1 16 java.util.Hashtable$EmptyIterator 
588:  1 16 java.util.Collections$EmptySet 
Total :  79700 8894800 
Heap traversal took 1.288 seconds. 
+0

Si può provare a premere [CTRL] + [SYSREQ] sulla console in cui viene eseguito il server. Questo ti darà un dump del thread che sarà verboso come si ottiene. – JimmyB

risposta

1

Discussione 5554 potrebbe indicare che hai un sacco di oggetti con i metodi di finalizzazione, e/o di qualche problema con un metodo di finalizzazione. Potrebbe valere la pena di guardarlo.

non ero familiarità con jstack, ma sembra che emette meno informazioni che il filo discariche sono più familiarità con. Potrebbe essere utile provare a ottenere un dump di thread: kill -QUIT java_pid. Si noti che il dump va allo stdout che potrebbe essere per la console o per registrare il file a seconda della configurazione.

Se è difficile capire dove stdout è diretto a, e supponendo che sta andando in un file, è possibile utilizzare find dalla recente data di modifica per identificare i file candidati. Ciò è suggerito in un commento a this blog post:

è possibile eseguire trovare [2] comando al directory principale e scoprire che cosa cambiato negli ultimi x secondi. Di solito ho usato find per aiutarmi a accedere a tutti i log modificati negli ultimi 10 minuti, ad es .: trovare /var/tomcat -mmin -3 -print (stampa tutti i file modificati sotto /var/tomcat in hte ultimi 3 minuti).

Si noti che se si esegue il JVM con -Xrs, questo significa che il gestore SIGQUIT segnale non verrà installato e non sarà in grado di utilizzare tale mezzo di richiedere una discarica thread.

+0

5554 è il finalizzatore e deve essere parcheggiato a meno che non ci sia qualcosa da finalizzare.Non dovrebbe impedire al processo di terminare. Il kill -QUIT è un'ottima idea in quanto potrebbe aiutarti a capire cosa sta succedendo con 5555 che sembra il colpevole più probabile. – philwb

+0

Proverò 'kill -QUIT' la prossima volta che si verifica il problema e vedere se questo fornisce ulteriori informazioni, grazie. Penso che potrebbero esserci alcuni finalizzatori personalizzati in giro, ma tutto quello che dovrebbero fare è chiudere i file aperti. Immagino che sia veloce e abbastanza sicuro, ma forse non ... –

+0

Penso che @philwb abbia ragione. Probabilmente non c'è niente di sbagliato con i finalizzatori - il thread del finalizzatore è in attesa di qualcosa da fare, non bloccato mentre si lavora. – sudocode

2

questo potrebbe essere causato anche da una memoria insufficiente. Vorrei provare due cose:

  • Abilita discarica automatica mucchio sul OutOfMemory da addingJVM parametri

    -XX: + HeapDumpOnOutOfMemoryError XX: HeapDumpPath =/tmp

  • tenta di connettersi al vostro JVM con JConsole e vedere se c'è qualche modello insolito

+0

Sfortunatamente jconsole non sembra collegarsi ad esso (appena va in time se provo da remoto, e se lo eseguo dal server il PID relativo è disattivato nella lista). Vedrò cosa posso fare per ottenere quei parametri sulla giusta invocazione JVM. –

2

Sospetto di un problema di memoria. Potresti voler vedere il processo usando jstat e fare un dump dell'heap usando jmap nel tempo necessario per terminare il processo. Vedi se jstat indica GC continuo. Inoltre, si consiglia di controllare la salute del sistema in generale (descrittori di file aperti, rete, ecc.). La memoria sarebbe la più semplice, quindi consiglio vivamente di iniziare con essa.

+0

Purtroppo jstat mi dà il messaggio 'Impossibile sincronizzarsi con il target'. jmap sembra essere in grado di produrre alcune informazioni (aggiornerò la domanda sopra). –

+0

Mi sembra di essere in grado di ottenere un heap dup con 'jmap -F -dump: format = b, file = heap.bin 894' oltre all'istogramma sopra, ma non sono ancora abbastanza sicuro di cosa fare con esso. –

+0

puoi usare eclipse MAT per esaminare il dump dell'heap. cercare sospetti di perdite. tuttavia, è strano che tu non sia in grado di usare jstat. che comando stai usando? – aishwarya

3

Si può sempre fare un strace -f -p pid per vedere ciò che il processo di Java sta facendo. Dal suo aspetto (non è possibile ottenere jstack senza -F e Thread 5548 non mostra stack di chiamate ed è IN_VM), sembra che il thread 5548 stia richiedendo troppo per fare qualcosa, o che sia possibilmente in un ciclo infinito.

+0

Eseguendo 'strace -f -p 894' ottengo una pila di righe che dicono' [pid 900] sched_yield() = 0' ... Interessante ... –

+0

@MattSheppard: Da questo punto, seguirò i consigli di bestsss e ottenere alcuni backtrace. Se il tuo sistema ha 'pstack', fai semplicemente' pstack '. Altrimenti dovresti fare 'gdb/path/to/java ' e da gdb 'bt' e' quit'. – ninjalj

+0

Ci proverò la prossima volta che si verifica. –

1

Sto riscontrando un problema simile, il mio jvm JBOSS ottiene un loop infinito, alla fine ottiene OutOfMemory, non posso uccidere il processo ma Kill -9. Sospetto il problema della memoria nella maggior parte dei casi.

2

Dai istantanea mentre il processo è in esecuzione normalmente via jstack -F (-F deve essere presente produce istantanea diverso solo jstack). I numeri di thread non sono Thread.id ma system one. 5548 sembra essere stato creato prima di Finalizer e RefCounter (non sono la fonte del problema), quindi dovrebbe essere una discussione GC o una compilatrice.

100% probabilmente significa qualche errore nel monitor. I monitor Java (hotspot) utilizzano un meccanismo di blocco di rotazione molto semplice per garantire la proprietà.

E naturalmente, collegare un debugger - GDB per verificare dove si è bloccato esattamente il processo.

0

Ecco alcuni strumenti che è possibile utilizzare per localizzare la parte del processo che richiede CPU:

  • perf/oprofile, soprattutto opannotate - ottimo per visitare i cicli di ciò che il codice diavolo sta consumando
  • strace , gstack/gdb (come menzionato da altri)
  • systemtap è enormemente potente, ma limitato in alcuni degli stessi modi degli strumenti basati su ptrace (se il problema non riguarda un sysc tutto, è molto meno efficace).
Problemi correlati