Interbloqueos son posibles en cualquiera de los multi-subprocesos de una aplicación Java. Han sido un problema desde que los primeros multi-subprocesos fueron implementados. Por ejemplo: Una aplicación puede pasar por un ciclo completo de pruebas, ser liberada, realizar pruebas adicionales y finalmente ser implementada para usos de misión crítica. Conforme el uso de la aplicación incrementa, algunos componentes críticos dejan de responder repentinamente. La única opción del administrador del sistema es eliminar súbitamente la aplicación y reiniciarla para que siga funcionando.

Lo que suele pasar es que los usuarios de la aplicación recurren al administrador del sistema por la presencia de problemas, pérdida de ventas u otros daños causados por el tiempo de inactividad. Los desarrolladores son notificados que la aplicación se ha congelado y debe ser resuelto inmediatamente. Desafortunadamente, por lo general hay muy poca y/o en ocasiones ninguna información sobre la causa de un congelamiento. Los desarrolladores necesitan resolver el problema sin ninguna pista sobre que fue lo que pasó y/o determinar cual es el problema. Esto normalmente causa que se hagan "pruebas y ver qué pasa", lo cual nunca es bueno para cualquier persona involucrada.

Cuando un interbloqueo es detectado por el Wrapper, primero registrará un reporte detallado de los subprocesos exactos y objetos involucrados. Inmediatamente reiniciará la JVM para asegurarse que su aplicación Java reinicie su trabajo con un tiempo mínimo de inactividad. Esto signfica que no solo su aplicación Java seguirá operando, pero toda la información que se requiera para reportar el problema y exista una manera para poder ser arreglado. Deadlock

¿Qué es un Interbloqueo?

Interbloqueos suceden cuando dos o más subprocesos en un programa no tienen acceso a objetos y estan a la espera de ellos, los cuales nunca estarán disponibles.

Imagine a dos trabajadores Toño y Alfredo, ellos se dedican a escribir notas. Para llevarlo a cabo, necesitan tomar un cuaderno y una pluma, escribir la nota y después ponerlos de regreso en el escritorio. Los dos tienen un carácter fuerte, una vez que empiezan a trabajar no regresan el cuaderno y la pluma al escritorio hasta que hayan escrito la nota.

Que pasará cuando Toño toma el cuaderno y Alfredo toma la pluma al mismo tiempo? Toño esperará por la pluma y Alfredo esperará por el cuaderno. Ellos estan en una situación de interbloqueo. No hay manera alguna de que prosigan ya que ninguno regresará el cuaderno o la pluma hasta que completen su trabajo y escribir la nota.

Uno de ellos eventualmente se cansará y regresará el cuaderno o la pluma al escritorio. Sin embargo, esto no pasa con programas de computación, por lo tanto dos subprocesos han entrado en un estado de interbloqueo y continuarán esperando por largas horas. En algún momento el encargo notará que el trabajo no se esta llevando a cabo, lo cual resulta en un gran problema para la empresa.

Lo que hace que este interbloqueo sea un gran problema para reproducirlo y arreglarlo es el tiempo que tomará. Toño y Alfredo tal vez han trabajado juntos durante mucho tiempo, pero el simple hecho de que en algún momento de sus vidas se presenta la necesidad de escribir una nota al mismo tiempo. Por otra parte cuando se les pida que escriban notas al mismo tiempo, el problema se presentará constantemente.

¿Cómo resolver este dilema?

La solución es decirle a Toño y Alfredo que cuando escriban una nota, tienen que tratar de tomar primero el cuaderno y después tomar la pluma. En algunas ocasiones uno de ellos tendrá que esperar un momento hasta que uno de ellos ponga ya sea el cuaderno o la pluma en el escritorio y evitar que surjan problemas.

Solución

En este ejemplo con los dos trabajadores, el problema esta claro y por lo tanto fácil de resolver. En una aplicación existen un gran número de recursos y miles de líneas de código, esto hace difícil de identificar un problema específico para después tratar de arreglarlo. Un interbloqueo real en ocasiones incluye varios recursos y subprocesos que son usados en combinaciones, que no fueron anticipadas por los desarrolladores de sistemas.

Interbloqueos por naturaleza tienden a ocurrir con una base de datos real que en un entorno de pruebas, ya que una base de datos suele tener una gran variedad y grandes volumes de información. Así cuando Toño y Alfredo tienen que registrar pocos mensajes, el sistema que usen trabajará bien. Pero cuando hay mucha actividad se vuelve más vulnerable que el sistema experimente este tipo de problemas.

Se le puede pedir a Toño y Alfredo que sigan un forma de trabajo con el cual se evite que surjan problemas, lo cual sería lo mas práctico. Sin embargo, en realidad los sistemas son diseñados por diferentes desarrolladores cada uno de ellos crea su propia lista de tareas y estructuras de trabajo. Cualquier conjunto de operaciones esta bien, pero puede causar problemas cuando se usen juntas.

Mientras que el Java Service Wrapper no puede evitar que un Interbloqueo ocurra, el Wrapper cuenta con funciones avanzadas para detectarlos y que puedan ser arreglados antes de que un humano se de cuenta que algo anda mal. De la misma manera el Wrapper recaba y registra valores con una descripción detallada exactamente del problema que se presentó. Esto hace más fácil a un desarrollador de entender y de una manera rápida arreglar la causa del problema.

El Wrapper tiene la habilidad de monitorear una aplicación que este totalmente trabajando, sin causar virtualmente problemas en el rendimiento de la misma. Cuando se detecta un interbloqueo, generará un reporte en el archivo de registro de valores del Wrapper como el que se muestra a continuación:

Ejemplo del Registro de Valores de un Interbloqueo:
WrapperManager Error: Found 2 deadlocked threads!
WrapperManager Error: =============================
WrapperManager Error: "Worker-1" tid=18
WrapperManager Error:   java.lang.Thread.State: BLOCKED
WrapperManager Error:     at com.example.Worker1.pickUpPaper(Worker1.java:64)
WrapperManager Error:       - waiting on <0x000000002fcac6db> (a com.example.Paper) owned by "Worker-2" tid=17
WrapperManager Error:     at com.example.Worker1.pickUpPen(Worker1.java:83)
WrapperManager Error:       - locked <0x0000000029c56c60> (a com.example.Pen)
WrapperManager Error:     at com.example.Worker1.logMessage(Worker1.java:22)
WrapperManager Error:     at com.example.Worker1.run(Worker1.java:42)
WrapperManager Error:
WrapperManager Error: "Worker-2" tid=17
WrapperManager Error:   java.lang.Thread.State: BLOCKED
WrapperManager Error:     at com.example.Worker2.pickUpPen(Worker2.java:83)
WrapperManager Error:       - waiting on <0x0000000029c56c60> (a com.example.Pen) owned by "Worker-1" tid=18
WrapperManager Error:     at com.example.Worker2.pickUpPaper(Worker2.java:64)
WrapperManager Error:       - locked <0x000000002fcac6db> (a com.example.Paper)
WrapperManager Error:     at com.example.Worker2.logMessage(Worker2.java:22)
WrapperManager Error:     at com.example.Worker2.run(Worker2.java:42)
WrapperManager Error:
Un Interbloqueo fue detectado.  Reiniciando JVM. 
WrapperManager Error: =============================

Después que se detecta un interbloqueo, el Wrapper puede configurarse para ejecutar un gran número de acciones. En la mayoría de los casos, enviar una notificación a través de un email y después reiniciar la aplicación es la mejor opción. La salida de datos que se incluirá en el email como se muestra en la parte de arriba hará mas fácil que un desarrollador pueda identificar el problema y arreglarlo. El reinicio ayudará a reducir el impacto del problema a usuarios, al poner una vez más en funcionamiento la aplicación lo más pronto posible sin la necesidad de que se experimente retraso alguno.

Con el reporte es muy fácil de observar que el interbloqueo fue causado por los subprocesos del "Trabajador-1" y el "Trabajador-2", e identificar en su respectiva pila de llamadas el porqué se presentó dicho problema. La salida de datos proporciona una manera más clara y específica de cuales fueron las instancias de objetos que fallaron.

Después de todo esto la máquina JVM tuvo que haber reiniciado automáticamente, lo que significa que dicho problema fue limitado solamente a las transacciones de los usuarios que se vieron afectados en ese específico tiempo de inactividad.

El Wrapper le ayuda a detectar problemas críticos incluyendo:

Solución Técnica

Al usar la propiedad para detectar interbloqueos con el Java Service Wrapper es también muy fácil de agregar otras configuraciones de propiedades al archivo de configuración del Wrapper.

La aplicación de ejemplo TestWrapper que viene incluida con el Java Service Wrapper tiene esta función habilitada por defecto. Simplemente ejecute la aplicación y presione el botón "Crear Interbloqueo" para verla en acción.

Detección Simple de Interbloqueos

Compatibilidad :3.5.0
Ediciones :Edición ProfesionaEdición EstándarEdición de la Comunidad (No Soportado)
Plataformas :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

El Java Service Wrapper hace posible controlar:

Una configuración puede ser como lo que a continuación se presenta:

Ejemplo de la detección y registro de valores de un Interbloqueo:
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

Notificación a Través de Correos Electrónicos

Compatibilidad :3.5.0
Ediciones :Edición ProfesionaEdición Estándar (No Soportado)Edición de la Comunidad (No Soportado)
Plataformas :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

En el previo ejemplo se registrará la causa del interbloqueo para después recuperar la aplicación. Esto es de gran ayuda para recibir notificaciones del problema. La siguiente configuración registra los datos del problema, renicia la máquina JVM y después envia una notificación a través de un correo electrónico:

Ejemplo para enviar Notificaciones de un interbloqueo:
# Detección de Interbloqueos.
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

# Notificación a Través de Correos Electrónicos
wrapper.event.default.email.smtp.host=smtp.example.com
wrapper.event.default.email.subject=[%WRAPPER_HOSTNAME%:%WRAPPER_NAME%:%WRAPPER_EVENT_NAME%] Event Notification
wrapper.event.default.email.sender=myapp-noreply@example.com
wrapper.event.default.email.recipient=sysadmins@example.com
wrapper.event.jvm_deadlock.email=TRUE
wrapper.event.jvm_deadlock.email.body=Un Interbloqueo fue detectado en el Servidor de Mensajes. Por favor verificar.
wrapper.event.jvm_deadlock.email.maillog=ATTACHMENT

Ejecución de Comandos Externos

Compatibilidad :3.5.0
Ediciones :Edición ProfesionaEdición Estándar (No Soportado)Edición de la Comunidad (No Soportado)
Plataformas :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

Cuando un interbloqueo ocurre, algunos datos pueden permanecer en un estado denominado "no limpio" por lo tanto necesitamos hacer el trabajo de limpiarlo. Mientras que esto es una buena idea y ayuda a que aplicaciones Java se recuperen de errores, esta funcionalidad necesitará de cambios constantes por parte del equipo que desarrolla su aplicación. Administradores de sistemas normalmente tienen la tarea de hacer que las cosas funcionen mientras se encuentra una solución a dichos problemas.

El Java Service Wrapper hace posible ejecutar un comando externo, una aplicación o archivo de procesamiento por lotes en respuesta a eventos específicos.

La siguiente configuración ofrece:

Ejemplo para ejecutar un comando externo al presentarse un interbloqueo:
# Detección de Interbloqueos.
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

# Ejecutar un comando externo al presentarse un Interbloqueo.
wrapper.event.jvm_deadlock.command.argv.1=../bin/DeadlockCleanup.bat
wrapper.event.jvm_deadlock.command.block=TRUE

Referencia: Bloqueos Mutuos (Deadlock)

El Java Service Wrapper proporciona un conjunto completo de propiedades de configuración que le permiten hacer que el Wrapper se adapte exactamente a sus necesidades. Por favor, lea la documentación de las propiedades individuales para ver todas las posibilidades además de los ejemplos mostrados anteriormente.