AIX® se bloque
S'il ne se produit pas d'interblocage entre les unités d'exécution, réfléchissez aux autres raisons pouvant expliquer pourquoi les unités d'exécution n'effectuent pas un travail utile.
- Les unités d'exécution sont à l'état "en attente", et attendent que le travail à effectuer leur soit "notifié".
- Les unités d'exécution se trouvent dans des cycles de veille explicites.
- Les unités d'exécution se trouvent dans des appels d'E-S en attente de travail.
La troisième raison, c'est-à-dire le cas où les unités d'exécution sont en attente d'E-S (par exemple sur des sockets) nécessite d'être analysé plus en détail. Le processus à l'autre extrémité de l'E-S a-t-il échoué ? Y a-t-il des problèmes réseau ?
Pour savoir comment l'outil javadump est utilisé pour diagnostiquer les boucles, voir THREADS. Si vous ne pouvez pas diagnostiquer le problème à l'aide du vidage java et si le processus semble toujours utiliser des cycles du processeur, cela signifie qu'il est entré dans une boucle sans fin ou qu'il est affecté par de très mauvaises performances. L'utilisation de ps -mp [process id] -o THREAD permet aux unités d'exécution d'un processus particulier d'être surveillées afin de déterminer quelles sont les unités d'exécution qui utilisent le temps UC. Si le processus est entré dans une boucle sans fin, il est probable qu'un petit nombre d'unités d'exécution utiliseront ce temps. Par exemple :
$ ps -mp 43824 -o THREAD
USER PID PPID TID ST CP PRI SC WCHAN F TT BND COMMAND
wsuser 43824 51762 - A 66 60 77 * 200001 pts/4 - java ...
- - - 4021 S 0 60 1 22c4d670 c00400 - - -
- - - 11343 S 0 60 1 e6002cbc 8400400 - - -
- - - 14289 S 0 60 1 22c4d670 c00400 - - -
- - - 14379 S 0 60 1 22c4d670 c00400 - - -
...
- - - 43187 S 0 60 1 701e6114 400400 - - -
- - - 43939 R 33 76 1 20039c88 c00000 - - -
- - - 50275 S 0 60 1 22c4d670 c00400 - - -
- - - 52477 S 0 60 1 e600ccbc 8400400 - - -
...
- - - 98911 S 0 60 1 7023d46c 400400 - - -
- - - 99345 R 33 76 0 - 400000 - - -
- - - 99877 S 0 60 1 22c4d670 c00400 - - -
- - - 100661 S 0 60 1 22c4d670 c00400 - - -
- - - 102599 S 0 60 1 22c4d670 c00400 - - -
...
Les unités d'exécution comportant la valeur "R" sous "ST" sont à l'état "exécutable", et peuvent donc accumuler du temps processeur. Que font ces unités d'exécution ? La sortie de ps montre le TID (Id de l'unité d'exécution du noyau) de chaque unité d'exécution. Il peut être mappé à l'ID d'unité d'exécution Java à l'aide de dbx. La sortie de la commande thread se présente comme suit :
thread state-k wchan state-u k-tid mode held scope function
$t1 wait 0xe60196bc blocked 104099 k no sys _pthread_ksleep
>$t2 run blocked 68851 k no sys _pthread_ksleep
$t3 wait 0x2015a458 running 29871 k no sys pthread_mutex_lock
...
$t50 wait running 86077 k no sys getLinkRegister
$t51 run running 43939 u no sys reverseHandle
$t52 wait running 56273 k no sys getLinkRegister
$t53 wait running 37797 k no sys getLinkRegister
$t60 wait running 4021 k no sys getLinkRegister
$t61 wait running 18791 k no sys getLinkRegister
$t62 wait running 99345 k no sys getLinkRegister
$t63 wait running 20995 k no sys getLinkRegister
En faisant correspondre la valeur du TID de ps avec la valeur k-tid de la commande dbx thread, vous pouvez voir que les méthodes en cours d'exécution dans ce cas sont reverseHandle et getLinkRegister.
Vous pouvez maintenant utiliser dbx pour générer la pile d'unité d'exécution C de ces deux unités d'exécution avec la commande dbx thread des numéros d'unité d'exécution dbx correspondants ($tx). Pour obtenir la trace de pile complète, y compris les cadres Java, mappez le numéro d'unité d'exécution dbx à la valeur pthread_t des unités d'exécution, qui est répertoriée par le fichier de vidage Java, et qui peut être obtenue à partir de la structure ExecEnv de chaque unité d'exécution à l'aide de l'afficheur de vidage. Pour cela, utilisez la commande dbx thread
info [dbx thread number]
, qui génère une sortie du type suivant :
thread state-k wchan state-u k-tid mode held scope function
$t51 run running 43939 u no sys reverseHandle
general:
pthread addr = 0x220c2dc0 size = 0x18c
vp addr = 0x22109f94 size = 0x284
thread errno = 61
start pc = 0xf04b4e64
joinable = yes
pthread_t = 3233
scheduler:
kernel =
user = 1 (other)
event :
event = 0x0
cancel = enabled, deferred, not pending
stack storage:
base = 0x220c8018 size = 0x40000
limit = 0x22108018
sp = 0x22106930
Elle montre que la valeur de TID d ps (k-tid dans dbx) correspond au numéro d'unité d'exécution dbx 51, qui a un pthread_t de 3233. En recherchant le pthread_t dans le fichier de vidage java, vous avez maintenant ne trace de pile complète :
"Worker#31" (TID:0x36288b10, sys_thread_t:0x220c2db8) Native Thread State:
ThreadID: 00003233 Reuse: 1 USER SUSPENDED Native Stack Data : base: 22107f80
pointer 22106390 used(7152) free(250896)
----- Monitors held -----
java.io.OutputStreamWriter@3636a930
com.ibm.servlet.engine.webapp.BufferedWriter@3636be78
com.ibm.servlet.engine.webapp.WebAppRequestDispatcher@3636c270
com.ibm.servlet.engine.srt.SRTOutputStream@36941820
com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection@36d84490 JNI pinning lock
----- Native stack -----
_spin_lock_global_common pthread_mutex_lock - blocked on Heap Lock
sysMonitorEnterQuicker sysMonitorEnter unpin_object unpinObj
jni_ReleaseScalarArrayElements jni_ReleaseByteArrayElements
Java_com_ibm_servlet_engine_oselistener_nativeEntry_NativeServerConnection_nativeWrite
------ Java stack ------ () prio=5
com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection.write(Compiled Code)
com.ibm.servlet.engine.srp.SRPConnection.write(Compiled Code)
com.ibm.servlet.engine.srt.SRTOutputStream.write(Compiled Code)
java.io.OutputStreamWriter.flushBuffer(Compiled Code)
java.io.OutputStreamWriter.flush(Compiled Code)
java.io.PrintWriter.flush(Compiled Code)
com.ibm.servlet.engine.webapp.BufferedWriter.flushChars(Compiled Code)
com.ibm.servlet.engine.webapp.BufferedWriter.write(Compiled Code)
java.io.Writer.write(Compiled Code)
java.io.PrintWriter.write(Compiled Code)
java.io.PrintWriter.write(Compiled Code)
java.io.PrintWriter.print(Compiled Code)
java.io.PrintWriter.println(Compiled Code)
pagecompile._identifycustomer_xjsp.service(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.JSPState.service(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doService(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doGet(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
A l'aide de la trace de pile complète, il est possible d'identifier toute boucle sans fin. L'exemple précédent illustre l'utilisation de spin_lock_global_common
, qui est une attente à l'état occupé sur un verrouillage, d'où l'utilisation de temps UC.