Zajętość systemu AIX® zawiesza się

Jeśli między wątkami nie występuje zakleszczenie, należy wziąć pod uwagę inne przyczyny, dla których wątki nie są wykonujące użytecznej pracy.

Zwykle stan ten występuje z jednej z następujących przyczyn:
  1. Wątki są w stanie 'wait', oczekując na 'powiadomiony' o pracy do wykonania.
  2. Wątki są w jawnych cyklach uśpienia.
  3. Wątki są w wywołaniach we/wy oczekujących na wykonanie prac.
Dwa pierwsze powody wskazują na błąd w kodzie Java™ , albo w aplikacji, albo na podstawie standardowych plików klas zawartych w pakiecie SDK.

Trzecia przyczyna, w której wątki oczekują (na przykład na gniazdach) na potrzeby operacji we/wy, wymaga dalszego badania. Czy proces na drugim końcu operacji we/wy nie powiódł się? Czy istnieją jakieś problemy z siecią?

Aby sprawdzić, w jaki sposób narzędzie javadump jest używane do diagnozowania pętli, patrz WĄTKI. Jeśli nie można zdiagnozować problemu z poziomu javadump i jeśli proces nadal wydaje się korzystać z cykli procesora, to albo on wszedł w nieskończoną pętlę lub cierpi na bardzo złą wydajność. Użycie komendy ps -mp [ id procesu] -o THREAD umożliwia monitorowanie poszczególnych wątków w określonym procesie w celu określenia, które wątki używają czasu procesora. Jeśli proces wszedł w nieskończoną pętlę, jest prawdopodobne, że mała liczba wątków będzie używać tego czasu. Na przykład:

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

Te wątki o wartości 'R' w obszarze 'ST' są w stanie 'runnable' i w związku z tym są w stanie zgromadzić czas procesora. Jakie są te wątki? Dane wyjściowe komendy ps przedstawiają identyfikator TID (identyfikator wątku jądra) dla każdego wątku. Można to odwzorować na identyfikator wątku Java za pomocą komendy dbx. Dane wyjściowe komendy dbx thread podaje wynik w postaci:

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

Dopasując wartość TID z ps do wartości k-tid z komendy dbx thread , można zauważyć, że obecnie działające metody w tym przypadku to reverseHandle i getLinkRegister.

Teraz można użyć komendy dbx w celu wygenerowania stosu wątków C dla tych dwóch wątków, używając komendy dbx thread dla odpowiednich numerów wątków dbx ($tx). Aby uzyskać pełny stos wywołań, w tym ramki Java, odwzoruj numer wątku dbx na wątki pthread_t , które są wymienione w pliku Javadump, i można je uzyskać z struktury ExecEnv dla każdego wątku za pomocą przeglądarki Dump Viewer. W tym celu należy wykonać komendę dbx thread info [dbx thread number], która generuje dane wyjściowe formularza:

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

Pokazuje, że wartość TID z ps (k-tid w dbx) odpowiada nitkowi dbx o numerze 51, który ma pthread_t z 3233. Szukając pliku pthread_t w pliku Javadump, masz teraz pełne dane śledzenia stosu:

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

Przy użyciu pełnego śledzenia stosu można określić dowolną nieskończoną pętlę, która może mieć miejsce. W poprzednim przykładzie przedstawiono użycie komendy spin_lock_global_common, która jest zajętym oczekiwaniem na blokadę, a więc użycie czasu pracy procesora.