Red de conocimiento informático - Material del sitio web - Cómo analizar volcados de subprocesos

Cómo analizar volcados de subprocesos

Los volcados de subprocesos son necesarios cuando un programa web Java se ejecuta lentamente o falla. Si cree que los volcados de subprocesos son complicados, este artículo puede ayudarle. Analizará subprocesos en Java, cómo crear subprocesos, cómo administrar subprocesos, cómo volcar subprocesos de un programa en ejecución y cómo analizar subprocesos en busca de bloqueos y cuellos de botella. Este artículo es el resultado obtenido durante la depuración de la aplicación.

Java y subprocesos

Los servidores web utilizan entre decenas y cientos de subprocesos para manejar un gran número de usuarios simultáneos. Si varios subprocesos utilizan **** para disfrutar de los recursos, no se puede evitar la competencia por los datos entre subprocesos y, en ocasiones, pueden producirse puntos muertos.

La contención de subprocesos significa que diferentes subprocesos en un programa de red acceden a recursos disfrutados, y un subproceso espera a que otro subproceso libere el bloqueo. Por ejemplo, al iniciar sesión, el hilo de registro primero debe adquirir el bloqueo y luego acceder al recurso disfrutado.

Un punto muerto es un tipo especial de contención de subprocesos en el que dos o más subprocesos deben esperar a que otros subprocesos completen sus tareas.

La contención de subprocesos puede causar una variedad de problemas diferentes. Para analizar estos problemas, debe utilizar un volcado de subprocesos (Thread Dump) para registrar el estado real de cada subproceso.

Antecedentes de los subprocesos de Java

Sincronización de subprocesos

Se pueden ejecutar varios subprocesos al mismo tiempo para garantizar que varios subprocesos utilicen ****-enjoyed. de una manera común Recurso, la sincronización de subprocesos se utiliza para garantizar que solo un subproceso pueda acceder al recurso disfrutado a la vez.

La sincronización de subprocesos en Java se puede lograr mediante monitores. Cada objeto Java tiene un monitor, que sólo puede ser propiedad de un hilo. Cuando un subproceso desea adquirir un monitor propiedad de otro subproceso, debe ingresar a una cola de espera hasta que ese subproceso libere el monitor.

Estado del hilo

Para analizar el volcado del hilo, primero debe comprender el estado del hilo. El estado del hilo se encuentra en java.lang.Thread.State.

NUEVO: El hilo ha sido creado pero aún no se ha ejecutado

RUNNABLE: El hilo está ocupando la CPU y realizando tareas

BLOQUEADO: El hilo debe espere a que otro hilo libere el bloqueo. Obtenga el monitor.

ESPERANDO: llame a los métodos de espera, unión y estacionamiento para hacer que el hilo espere. - Espere indefinidamente

TIMED_WAITING: llame a los métodos Sleep, wait, join y park para hacer que el hilo espere; el tiempo de espera es limitado

Tipo de hilo

Los subprocesos en Java se pueden dividir en dos tipos:

1. Subproceso en segundo plano

2. Subproceso que no es en segundo plano

Cuando no se está ejecutando ningún otro subproceso que no sea en segundo plano, El hilo en segundo plano finalizará. Incluso si no crea subprocesos, las aplicaciones Java crean muchos subprocesos de forma predeterminada. La mayoría de ellos son subprocesos en segundo plano, que se utilizan principalmente para realizar tipos de tareas como gc o jmx.

Los subprocesos abiertos desde el método "static void main(String[] args)" se denominan subprocesos que no son en segundo plano. hilos Cuando se detiene, todos los demás hilos en segundo plano también se detendrán.

Obtener un volcado de subprocesos

Se introducirán tres métodos comunes. Tenga en cuenta que hay muchas otras formas de obtener volcados de subprocesos. Los volcados de subprocesos solo muestran el estado del subproceso en el momento de la medición. Por lo tanto, para ver cambios en el estado del hilo, se recomienda ejecutarlo de 5 a 10 veces cada 5 segundos.

Dapplication.home=/home1/user/java/jdk.1.6.0_24 -Xms8m

Get Thread Dump usa PID como parámetro jstack

[user@linux ~]$ jstack - f 5824

Obtener volcado de subprocesos Utilice jVisualVM para obtener el conjunto de datos del subproceso

Obtener volcado de subprocesos mediante jVisualVm

La marca a la izquierda indica el proceso actualmente en ejecución. Puede ver información del hilo en tiempo real haciendo clic en el proceso que desea ver y seleccionando la opción en tiempo real. Haga clic en el botón a la derecha del volcado de subprocesos para obtener el archivo de volcado de subprocesos

Genere el archivo en la terminal de Linux

Use el comando ps -ef para obtener el proceso Java actualmente en ejecución

[usuario@linux ~]$ ps - ef | grep java

usuario 2477 1 0 23 de diciembre 00:10:45 ...

usuario 25780 25361 0 15:02 pts/3 00:00:02 ./jstatd -J -Djava.security.policy=jstatd.all.policy -p 2999

usuario 26335 25361 0 15:49 pts/3 00:00 :00 grep java

Utilice el pid extraído como argumento para eliminar -SIGQUIT(3) y obtener un volcado del hilo.

Información del subproceso en el archivo de volcado de subprocesos

"pool-1-thread-13 " prio=6 tid=0x000000000729a000 nid=0x2fb4 ejecutable [0x0000000007f0f000] java.lang.Thread Estado: RUNNABLE en java.net.SocketInputStream.java: 158) - lt bloqueado; (inputStreamReader.java: 167) en java.io.StreamDecoder ( StreamDecoder.java:306) en sun.nio.cs.BufferedReader.fill(BufferedReader.java:136) en java.io.BufferedReader.readLine(BufferedReader.java:299) - bloqueado lt; InputStreamReader) - Bloquear.

InputStreamReader) en java.io.BufferedReader.readLine(BufferedReader.java:362)

Nombre del hilo: el nombre del hilo utilizado al generar un hilo usando la clase Java.lang.Thread, se llamará Thre- (número), pero cuando se genera un hilo usando la clase java.util.ThreadFactory, se llamará Thre- (número). Concurrencia, clase ThreadFactory, se llamará pool-(Number) -thread-(Number)

Prioridad: representa la prioridad del hilo

ID del hilo: representa la unicidad del ID del subproceso (puede obtener información útil a través del ID del subproceso, incluido el uso de la CPU o el uso de la memoria)

Estado del subproceso: representa el estado del subproceso.

Estado del hilo: indica el estado del hilo

Pila de llamadas del hilo: indica la información de la pila de la llamada del hilo

Tipo de modo de volcado del hilo

Cuando no se puede adquirir un bloqueo (bloqueo)

Cuando un hilo ocupa un bloqueo y ningún otro hilo puede adquirirlo, todo el rendimiento de la aplicación se degrada. En el siguiente ejemplo,

BLOCKED_TEST pool-1-thread-1 se está ejecutando para obtener <0x0000000780a000b0gt>, mientras BLOCKED_TEST pool-1-thread-2 y BLOCKED_TEST pool-1-thread-3 están esperando Get. la cerradura.

RUNNABLE en java.io.FileOutputStream.writeBytes(Método nativo) en java.io.FileOutputStream.write(FileOutputStream.java:282) en java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65) en java.io.BufferedOutputStream. flush(BufferedOutputStream.java:123) - bloqueado <0x0000000780a31778gt; cs.StreamEncoder.writeBytes(StreamEncoder.java:202) en sun.nio.cs.flushBuffer(StreamEncoder.java:85) - bloqueado lt;0x0000000780a040c0gt; java. io.OutputStreamWriter).OutputStreamWriter) en java.io.flushBuffer (OutputStreamWriter.java:168) en java.io.PrintStream.newLine(PrintStream.java:496) - bloqueado lt;0x0000000780a04118gt (a java.io.PrintStream.newLine; (PrintStream.java:496).io.PrintStream) en java.io.PrintStream.println(PrintStream.java:687) - bloqueado lt;0x0000000780a04118gt; (un java.io.PrintStream) en com.threaddump.ThreadBlockedState.monitorLock( ThreadBlockedState.java:44) - bloqueado lt;0x0000000780a000b0gt; (a com.nbp.threaddump.ThreadBlockedState$1.run(ThreadBlockedState.java:7) en java.util.concurrent.ThreadPoolExecutor$Worker .runTask(ThreadPoolExecutor.java:886) en java.util.concurrent.Worker.run(ThreadPoolExecutor.java:908) en java.lang.Thread.run(Thread.java:662) bloqueado propiedad

Sincronizador: - lt;0x0000000780a31758 gt; (a java.util.concurrent.locks.ReentrantLock$Non't)ReentrantLock$NonfairSync) "BLOCKED_TEST pool-1-thread-2" prio=6 tid=0x0000000007673800 nid=0x260c esperando monitor Entrada [0x0000000008ABF000] java.lang.thread.state: bloqueado (en el monitor de objetos) en com.nbp.theplatform.threaddump.threadblockedstate.monitorlock (Threadblockedstate.java: 43) - Esperando para bloquear LT; .theplatform.threaddump.ThreadBlockedState) en com.nbp.theplatform.threaddump.ThreadBlockedState$2.run(ThreadBlockedState.java:26) en java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) en java. util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) en java.lang.Thread.run(Thread.java:662) Bloqueado propio sincronizable: - lt;0x0000000780b0c6a0gt; run(java.lang.Thread.java:662)util.concurrent.locks.ReentrantLock$NonfairSync) "BLOCKED_TEST pool-1-thread-3" prio=6 tid=0x00000000074f5800 nid=0x1994 esperando la entrada del monitor [0x0000000008bbf000] java. lang.Thread.State: BLOQUEADO (en el monitor de objetos) en com.nbp.theplatform.threaddump.ThreadBlockedState .monitorLock(ThreadBlockedState.java: 42) - esperando bloquear lt; theplatform.threaddump.ThreadBlockedState$3.run(ThreadBlockedState.java:34) en java.util.concurrent.ThreadPoolExecutor$2.run(java.util.c

oncurrent.ThreadPoolExecutor$2.run(java.util.concurrent.ThreadPoolExecutor$2.run(java.util.concurrent.ThreadPoolExecutor.java:34)ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) en java.util.concurrent.ThreadPoolExecutor $Worker.run(ThreadPoolExecutor.java:908) en java.lang.Thread.run(Thread.java:662) Sincronizadores propietarios bloqueados: - lt;0x0000000780b0e1b8gt (a java.util.concurrent.locks.LOCs) util.concurrent; .locks.ReentrantLock$NonfairSync)

Cuando está en un estado de punto muerto

El subproceso A necesita adquirir el bloqueo del subproceso B para continuar ejecutando la tarea, y el subproceso B necesita adquirir el bloqueo. de hilo Un bloqueo para continuar ejecutando la tarea. En el volcado del hilo, se puede ver que el hilo DEADLOCK_TEST-1 posee el bloqueo 0x00000007d58f5e48 y está intentando adquirir el bloqueo 0x00000007d58f5e60. Además, el subproceso DEADLOCK_TEST-2 posee el bloqueo 0x00000007d58f5e60 e intenta adquirir el bloqueo 0x00000007d58f5e78. DEADLOCK_TEST-3 El subproceso posee el bloqueo 0x00000007d58f5e78 y está intentando adquirir el bloqueo 0x00000007d58f5e48. Como puede ver, cada subproceso está esperando el bloqueo del otro subproceso y este estado no cambia hasta que un subproceso abandona el bloqueo.

Demonio "DEADLOCK_TEST-1" prio=6 tid=0x000000000690f800 nid=0x1820 esperando la entrada del monitor [0x000000000805f000] java.lang.Thread Estado: BLOQUEADO (en el monitor de objetos) en com.nbp.theplatform. threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197) - esperando bloquear lt;0x00000007d58f5e60gt; (un com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor) en com.nbp.theplatform.threaddump.ThreadDead LockState$DeadlockTh leído. monitorOurLock (ThreadDeadLockState.java:182) - bloqueado Puede tener sincronizadores: - Ninguno "DEADLOCK_TEST-2" daemon prio=6 tid=0x0000000006858800 nid=0x17b8 esperando la entrada del monitor [0x000000000815f000] java.lang.Thread.State: BLOQUEADO (en el objeto) monitor) en com.nbp.theplatform. threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197) - esperando bloquear lt; 0x00000007d58f5e78gt; nbp. theplatform.threaddump.ThreadDeadLockState.goMonitor Deadlock(ThreadDeadLockState .java:197) - esperando bloquear lt; 0x00000007d58f5e78gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)ThreadDeadLockState$DeadlockThread.monitorOurLo ck(ThreadDeadLockState.java:182)

- bloqueado lt;0x00000007d58f5e60gt; (a com.nbp.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135) Sincronizadores de propiedad bloqueados: - Ninguno "DEADLOCK_TEST-3" prio=6 tid=0x0000000006859000 nid=0x25d c esperando la entrada del monitor [ 0x000000000825f000] java.lang.Thread.State: BLOQUEADO (en el monitor de objetos) en com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java: 197) - esperando bloquear nbp (un archivo com.nbp.theplatform. threaddump.ThreadDeadLockState$ Monitor) en com.nbp.theplatform.threaddump .ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135) Sincronizadores propietarios bloqueados: - Ninguno

Esperando continuamente mensajes del servicio remoto

El hilo parece normal porque su estado siempre es EJECUTABLE, pero cuando ordenas el volcado del hilo por tiempo, puedes ver que el hilo socketReadThread siempre está leyendo el socket