AIX® se cuelga ocupado

Si no hay ningún punto muerto entre hebras, considere otras razones de porqué las hebras no están realizando trabajo útil.

Normalmente, este estado se produce por una de las razones siguientes:
  1. Las hebras están en un estado 'wait' en espera de ser 'notificadas' sobre trabajo que se debe realizar.
  2. Las hebras están en ciclos de suspensión explícita.
  3. Las hebras están en llamadas de E/S a la espera de realizar trabajo.
Las dos primeras razones implican un error en el código Java™ , ya sea el de la aplicación o el de los archivos de clase estándar incluidos en el SDK.

La tercera razón, en la que las hebras están en espera (por ejemplo, en sockets) de E/S, requiere investigación adicional. ¿Ha fallado el proceso en el otro extremo de la E/S? ¿Existen problemas de red?

Para ver cómo se utiliza la herramienta javadump para diagnosticar bucles, consulte THREADS. Si no puede diagnosticar el problema a partir del volcado Java y si parece que el proceso aún está utilizando ciclos del procesador, éste ha entrado en un bucle infinito o su rendimiento es muy bajo. La utilización de ps -mp [ID de proceso] -o THREAD permite supervisar hebras individuales de un proceso determinado a fin de determinar qué hebras utilizan el tiempo de CPU. Si el proceso ha entrado en un bucle infinito, es probable que un pequeño número de hebras estará utilizando el tiempo. Por ejemplo:

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

Estas hebras con el valor 'R' en 'ST' se encuentran en un estado 'runnable' y, por lo tanto, pueden acumular tiempo de procesador. ¿Qué hacen estas hebras? La salida de ps muestra el TID (ID de hebra de kernel) de cada hebra. Esto se puede correlacionar con el ID de hebra Java utilizando dbx. La salida del mandato thread de dbx proporciona una salida con el formato de:

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

Correlacionando el valor de TID de ps con el valor de k-tid del mandato dbx thread, puede ver que los métodos que están en ejecución actualmente en este caso son reverseHandle y getLinkRegister.

Ahora puede utilizar dbx para generar la pila de hebra C para estas dos hebras utilizando el mandato thread de dbx para los números de hebra de dbx correspondientes ($tx). Para obtener el rastreo de pila completo, incluidos los marcos Java, correlacione el número de hebra dbx con el valor pthread_t de hebras, que se lista mediante el archivo de volcado Java, y se puede obtener de la estructura ExecEnv para cada hebra utilizando el visor de volcado. Hágalo con el mandato dbx thread info [dbx thread number], que genera una salida con el formato:

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

Lo que muestra que el valor de TID de ps (k-tid en dbx) se corresponde con el número de hebra de dbx 51, que tiene un pthread_t de 3233. Si busca pthread_t en el archivo de volcado Java, ahora tendrá un rastreo de pila completo:

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

Y, utilizando el rastreo de pila completo, debería ser posible identificar cualquier bucle infinito que se estuviera produciendo. El ejemplo anterior muestra el uso de spin_lock_global_common, que es una espera ocupada en un bloqueo, de ahí el uso del tiempo de CPU.