AIX® -Blockierungen mit hoher Auslastung

Wenn kein Deadlock zwischen den Threads vorliegt, sollten Sie nach anderen Ursachen suchen, weshalb die Threads nicht funktionieren.

Normalerweise tritt dieser Status wegen einer der folgenden Ursachen auf:
  1. Threads befinden sich im Wartestatus und warten auf Benachrichtigungen über zu erledigende Aufgaben.
  2. Threads befinden sich in einem expliziten Standbyzyklus.
  3. Threads befinden sich in E/A-Aufrufen und warten auf auszuführende Arbeiten.
Die ersten beiden Gründe implizieren einen Fehler im Java™ -Code, entweder den der Anwendung oder den der im SDK enthaltenen Standardklassendateien.

Der dritte Grund, bei dem Threads auf eine Eingabe/Ausgabe warten (z. B. auf Sockets) muss näher untersucht werden. Ist der Prozess am anderen Ende der Ein-/Ausgabe fehlgeschlagen? Liegen Netzprobleme vor?

Informationen dazu, wie das Java-Speicherauszug-Tool zur Diagnose von Schleifen verwendet wird, finden Sie unter THREADS. Wenn Sie das Problem nicht anhand des Javadumps diagnostizieren können und der Prozess weiterhin Prozessorzyklen zu verwenden scheint, befindet er sich entweder in einer Endlosschleife oder wird durch eine sehr schlechte Leistung verursacht. Mit dem Befehl ps -mp [process id] -o THREAD können Sie einzelne Threads in einem bestimmten Prozess überwachen und feststellen, welche Threads die CPU-Zeit belegen. Wenn sich der Prozess in einer Endlosschleife befindet, wird die Zeit wahrscheinlich von wenigen Threads belegt. Beispiel:

$ 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      -   - -
...

Die Threads mit dem Wert 'R' unter 'ST' befinden sich in einem 'ausführbaren' Status und können daher Prozessorzeiten akkumulieren. Womit sind diese Threads beschäftigt? Die Ausgabe von ps zeigt die TID (Kernel-Thread-ID) für jeden Thread. Diese kann mit dbxder Java-Thread-ID zugeordnet werden. Die Ausgabe des dbx-Befehls thread hat folgendes Format:

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

Wenn Sie den TID-Wert von ps mit dem Wert k-tid des dbx-Befehls thread abgleichen, sehen Sie, dass 'reverseHandle' und 'getLinkRegister' hier die derzeit aktiven Methoden sind.

Jetzt können Sie mithilfe des Befehls dbx den C-Thread-Stack für diese beiden Threads generieren. Verwenden Sie den dbx-Befehl thread für die entsprechenden dbx-Threadnummern ($tx). Um den vollständigen Stack-Trace einschließlich Java-Frames abzurufen, ordnen Sie die dbx-Threadnummer dem Wert pthread_t für Threads zu, der in der Java-Speicherauszugsdatei aufgelistet ist und über die Speicherauszugsanzeige aus der Struktur ExecEnv für jeden Thread abgerufen werden kann. Verwenden Sie hierfür den dbx-Befehl thread info [dbx thread number], der folgende Ausgabe generiert:

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

Der TID-Wert von ps (k-tid in dbx) entspricht der dbx-Threadnummer 51, die eine pthread_t von 3233 hat. Wenn Sie in der Java-Speicherauszugsdatei nach dem Wert für pthread_t suchen, haben Sie einen vollständigen Stack-Trace:

"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)

Mithilfe des vollständigen Stack-Trace sollten jegliche Endlosschleifen identifiziert werden können, die möglicherweise auftreten. Das vorherige Beispiel zeigt die Verwendung von spin_lock_global_common, einem aktiven Warten auf eine Sperre, also der CPU-Zeit.