Ejecutar la Aplicación de Ejemplo TestWrapper

Esta página describirá la aplicación de ejemplo TestWrapper, que viene incluida con el Wrapper para demostrar varias de sus funciones de recuperación de errores.

Ejecutar en una Consola

Para ejecutar la aplicación en una consola, ejecute el siguiente script ubicado en el directorio bin:

Windows:
TestWrapper.bat
Unix:
./testwrapper console

NOTA

Antes de la versión 3.0.5, el script testwrapper en UNIX intentaba escribir un archivo PID al directorio /var/run. Usuarios no raíz (non-root) tendrían que cambiar la variable PIDDIR del script a un directorio con los permisos apropiados. Esto ya no es un problema desde la versión 3.0.5, ya que el Wrapper ahora escribe el archivo PID en la misma ubicación que el script.

Al iniciar la aplicación, aparecerá la siguiente ventana:

También verá la siguiente salida en la consola:

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()

Comencemos con la salida de la consola. La primera columna de datos muestra el origen de la salida. Las líneas que empiezan con "wrapper" vienen de la aplicación nativa del Wrapper. Las líneas que empiezan con "jvm 1" vienen de la salida de la JVM. El número después de "jvm" indica el número de JVM(s) iniciadas(s) desde que se inició el Wrapper. Veremos como funciona cuando empezarmos a usar la interfaz de TestWrapper.

Por defecto, toda la salida de la consola también se registra en logs/wrapper.log. Sin embargo, el formato del archivo de registro está configurado para incluir también el nivel de registro y las marcas de tiempo de cada mensaje que se registra.

Salida en el Archivo de Registros:
STATUS | wrapper  | 2001/12/06 16:18:27 | --> Wrapper Started as Console
STATUS | wrapper  | 2001/12/06 16:18:28 | Launching a JVM...
INFO   | jvm 1    | 2001/12/06 16:18:29 | Initializing...
INFO   | jvm 1    | 2001/12/06 16:18:30 | Wrapper (Version 3.x.x)
INFO   | jvm 1    | 2001/12/06 16:18:30 | 
INFO   | jvm 1    | 2001/12/06 16:18:30 | start()

Es posible reconfigurar separadamente el formato, así como el nivel de registro de cada salida de datos. Esto se puede hacer usando las siguientes propiedades:

Por defecto, la aplicación de ejemplo TestWrapper le presenta una interfaz que muestra varios botones para probar diversas funcionalidades del Wrapper. A continuación se describe cada botón con la salida que verá en la consola si el botón está activado.

Como alternativa a la interfaz gráfica del usuario (GUI), la aplicación TestWrapper se puede controlar exclusivamente desde un terminal. Este modo, llamado 'console' (consola), tiene las mismas funcionalidades que la GUI, pero la aplicación esperará las entradas del usuario, y las pruebas se pueden activar escribiendo comandos en el terminal en lugar de pulsar botones.

Ejecutar TestWrapper Application en modo 'console':
jvm 1    | WrapperManager: Initializing...
jvm 1    | TestWrapper: Initializing...
jvm 1    | TestWrapper: start()
jvm 1    | TestWrapper: ActionServer Enabled.
jvm 1    | TestWrapper:   Telnet localhost 9999
jvm 1    | TestWrapper:   Commands:
jvm 1    | TestWrapper:     S: Shutdown
jvm 1    | TestWrapper:     H: Expected Halt
jvm 1    | TestWrapper:     R: Restart
jvm 1    | TestWrapper:     D: Thread Dump
jvm 1    | TestWrapper:     U: Unexpected Halt (Simulate crash)
jvm 1    | TestWrapper:     V: Access Violation (Actual crash)
jvm 1    | TestWrapper:     G: Make the JVM appear to be hung.
jvm 1    | TestWrapper:
jvm 1    |
jvm 1    | Start prompting for actions.
jvm 1    | Input an action ('help' for a list of actions):
help
jvm 1    | Read action: help
jvm 1    |
jvm 1    | [ACTIONS]
jvm 1    |    help                     : Shows this help message
jvm 1    |   Actions which should cause the Wrapper to exit cleanly:
jvm 1    |    stop0                    : Calls WrapperManager.stop(0)
jvm 1    |    exit0                    : Calls System.exit(0)
jvm 1    |    stopimmediate0           : Calls WrapperManager.stopImmediate(0)
jvm 1    |    stopandreturn0           : Calls WrapperManager.stopAndReturn(0)
jvm 1    |   Actions which should cause the Wrapper to exit in an error state:
jvm 1    |    stop1                    : Calls WrapperManager.stop(1)
jvm 1    |    exit1                    : Calls System.exit(1)
jvm 1    |    nestedexit1              : Calls System.exit(1) within WrapperListener.stop(1) callback
jvm 1    |    stopimmediate1           : Calls WrapperManager.stopImmediate(1)
jvm 1    |   Actions which should cause the Wrapper to restart the JVM:
jvm 1    |    access_violation_native  : Calls WrapperManager.accessViolationNative()
jvm 1    |    appear_hung              : Calls WrapperManager.appearHung()
jvm 1    |    halt0                    : Calls Runtime.getRuntime().halt(0)
jvm 1    |    halt1                    : Calls Runtime.getRuntime().halt(1)
jvm 1    |    restart                  : Calls WrapperManager.restart()
jvm 1    |    restartandreturn         : Calls WrapperManager.restartAndReturn()
jvm 1    |   Additional Tests:
jvm 1    |    appear_slow_1            : Calls WrapperManager.appearSlow(1)
jvm 1    |    appear_slow_5            : Calls WrapperManager.appearSlow(5)
jvm 1    |    appear_slow_reset        : Calls WrapperManager.appearSlow(0) to return to normal
jvm 1    |    deadlock                 : Executes some deadlocking code to test deadlock detection
jvm 1    |    outofmemory              : Simulates an OutOfMemoryError being thrown
jvm 1    |    ignore_events            : Makes this application ignore control events.
jvm 1    |    dump                     : Calls WrapperManager.requestThreadDump()
jvm 1    |    deadlock_out             : Deadlocks the JVM's System.out and err streams.
jvm 1    |    users                    : Start polling the current and interactive users.
jvm 1    |    groups                   : Start polling the current and interactive users with groups.
jvm 1    |    console                  : Prompt for actions in the console.
jvm 1    |    idle                     : Do nothing just run in idle mode.
jvm 1    |    properties               : Dump all System Properties to the console.
jvm 1    |    configuration            : Dump all Wrapper Configuration Properties to the console.
jvm 1    |    gc                       : Perform a GC sweep.
jvm 1    |    is_professional          : Displays whether or not this is a Professional Edition Wrapper.
jvm 1    |    is_standard              : Displays whether or not this is at least a Standard Edition Wrapper.
jvm 1    |    exec <cmd>               : Executes a managed child process.
jvm 1    |    exec_detached <cmd>      : Executes a detached child process.

Para lanzar la aplicación en modo 'console', es necesario añadir un argumento 'console' adicional. En UNIX, este argumento no debe ser confundido con el comando 'console' pasado al script (la palabra 'console' debe repetirse 2 veces al lanzar el script).

Windows:
TestWrapper.bat console
Unix:
./testwrapper console console

Se puede cerrar la aplicación a cualquier momento cerrando la ventana o usando los botones "Stop()" y "Exit()". También puede presionar CTRL-C en el terminal para solicitar un apagado limpio.

Probar las Características del Wrapper (Salidas Internas y Problemas)

Esta sección demostrará como el Wrapper responde a varios eventos. Cada uno de estos eventos puede probarse pulsando los botones de la interfaz de usuario.

Stop

La JVM sale limpiamente al llamar WrapperManager.stop(0).

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
jvm 1    | stop(0)
wrapper  | <-- Wrapper Stopped

Como puede ver, se llamó al método stop() de la aplicación y esta se detuvo limpiamente.

Exit

El botón Exit pone a prueba la habilidad del Wrapper de detectar una llamada inesperada a System.exit() y detener la aplicación correctamente.

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
jvm 1    | stop(0)
jvm 1    | here
wrapper  | <-- Wrapper Stopped

Como un ejercicio, edite su archivo conf/wrapper.conf y descomente la propiedad wrapper.disable_shutdown_hook=TRUE. (Asegúrese de volver a comentarla cuando haya terminado.)

Ahora vuelva a ejecutar la aplicación TestWrapper.

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | JVM exited unexpectedly.
wrapper  | Launching a JVM...
jvm 2    | Initializing...
jvm 2    | Wrapper (Version 3.x.x)
jvm 2    |
jvm 2    | start()

Notará que el Wrapper ya no detecta la llamada a System.exit(), por lo que piensa que la JVM se ha colgado y la reinicia.

Halt

El botón Halt llama a un método de bajo nivel para un apagado forzado de la JVM. En este caso, los ganchos de apagado no se ejecutan y el Wrapper no tiene forma de detectarlos.

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | JVM exited unexpectedly.
wrapper  | Launching a JVM...
jvm 2    | Initializing...
jvm 2    | Wrapper (Version 3.x.x)
jvm 2    |
jvm 2    | start()

Note que el Wrapper piensa que la JVM se ha colgado y la reinicia.

Solicitar Reinicio

Reinicia la máquina JVM limpiamente al llamar a WrapperManager.restart()

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | JVM requested a restart.
jvm 1    | stop(0)
wrapper  | Launching a JVM...
jvm 2    | Initializing...
jvm 2    | Wrapper (Version 3.x.x)
jvm 2    |
jvm 2    | start()

Como puede ver, se llamó al método stop() de la aplicación y esta se ha reiniciado limpiamente.

Violación de Acceso Nativo

El Java Service Wrapper incluye una biblioteca nativa liviana que se utiliza para manejar eventos del sistema. La biblioteca también contiene un método nativo, que se utiliza para realizar pruebas para provocar una violación de acceso en el código nativo debido a una referencia "NULL".

Dependiendo de la JVM, la salida de datos también será diferente.

Salida de Consola (JVM Oracle):
wrapper  | -->jvm 1    | WrapperManager: WARNING: Attempting to cause an access violation...
jvm 1    | #
jvm 1    | # A fatal error has been detected by the Java Runtime Environment:
jvm 1    | #
jvm 1    | #  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007fffc9aee46f, pid=14352, tid=12948
jvm 1    | #
jvm 1    | # JRE version: Java(TM) SE Runtime Environment (8.0_45-b15) (build 1.8.0_45-b15)
jvm 1    | # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.45-b02 mixed mode windows-amd64 compressed oops)
jvm 1    | # Problematic frame:
jvm 1    | # C  [wrapper.dll+0xe46f]  Java_org_tanukisoftware_wrapper_WrapperManager_accessViolationInner+0x1f
jvm 1    | #
jvm 1    | # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
jvm 1    | #
jvm 1    | # An error report file with more information is saved as:
jvm 1    | # C:\wrapper\bin\hs_err_pid14352.log
jvm 1    | #
jvm 1    | # If you would like to submit a bug report, please visit:
jvm 1    | #   http://bugreport.java.com/bugreport/crash.jsp
jvm 1    | # The crash happened outside the Java Virtual Machine in native code.
jvm 1    | # See problematic frame for where to report the bug.
jvm 1    | #
wrapper  | JVM exited unexpectedly.
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...
jvm 2    | TestWrapper: Initializing...

Como puede ver, una violación de acceso provocó que la JVM mostrara un volcado de error y luego terminara. El Wrapper inmediatamente detecta eso y después de una pausa de 5 segundos, reinicia la aplicación en una nueva JVM, como se ve en jvm 2. Toda la información disponible sobre el bloqueo (crash) ha sido registrada para referencia futura.

Simular bloqueo de JVM

Esta prueba hace que el Wrapper piense que la JVM se ha bloqueado. Después de 30 segundos, el Wrapper agota el tiempo de espera y decide que la JVM no volverá y la reinicia.

Salida de Consolat:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
jvm 1    | WARNING: Making JVM appear to be hung...
wrapper  | JVM appears hung: Timed out waiting for signal from JVM.
wrapper  | JVM did not exit on request, terminated
wrapper  | Launching a JVM...
jvm 2    | Initializing...
jvm 2    | Wrapper (Version 3.x.x)
jvm 2    |
jvm 2    | start()

Probar las Características del Wrapper (Salidas Externas)

La sección anterior cubrió todas las formas en las que una aplicación puede salir o terminar repentinamente por su cuenta. Existen otros factores externos de los cuales el Wrapper también puede protegerse.

CTRL-C

La mayoría de las aplicaciones Java terminan de forma bastante abrupta si el usuario presiona CTRL-C, cierra sesión en Windows, etc. Puede solucionar algunos de estos problemas con un Shutdown Hook (gancho de apagado). El Wrapper implementa esto utilizando una biblioteca nativa para capturar directamente las señales del sistema. Esto permite tener una aplicación Java instalada como un servicio de Windows sin que se detenga cuando un usuario cierra la sesión.

A modo de prueba, intente presionar CTRL-C en la consola (ventana de comandos).

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | CTRL-C trapped.  Shutting down.
jvm 1    | stop(0)
wrapper  | <-- Wrapper Stopped

También puede ver algunas variaciones de esto al cerrar sesión cuando la aplicación de la consola aún esté ejecutándose. El Wrapper terminará la aplicación correctamente.

Salida de la Consola:
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    | 
jvm 1    | start()
wrapper  | User logged out.  Shutting down.
jvm 1    | stop(0)
wrapper  | <-- Wrapper Stopped

En plataformas Unix, solo se puede presionar CTRL-C si se ha pasado el comando 'console' al script utilizado para iniciar el Wrapper.

Si el Wrapper se inició utilizando el comando 'start', entonces ha sido generado en un proceso diferente como un Servicio/Daemon, por lo que usted no podrá acceder a la consola. Para detener las instancias generadas del Wrapper, ejecute el mismo script utilizado para iniciar el Wrapper, solo que esta vez especifique el comando 'stop':

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | Shutting down.
jvm 1    | stop(0)
wrapper  | <-- Wrapper Stopped

Terminación del Proceso

También es posible aunque poco probable, que el proceso de la aplicación pudiera ser eliminado por otra aplicación. Esta prueba también simula casos en que la JVM muere repentinamente por su cuenta. En sistemas UNIX, se puede eliminar el proceso Java con una señal kill -9. En sistemas Windows, abra el Administrador de Tareas y seleccione la pestaña de Procesos. Después, busque el proceso java.exe a ser eliminado y elimínelo.

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
wrapper  | JVM exited unexpectedly.
wrapper  | Launching a JVM...
jvm 2    | Initializing...
jvm 2    | Wrapper (Version 3.x.x)
jvm 2    |
jvm 2    | start()

El Wrapper reiniciará la JVM sin ningún problema.

Si en lugar de eliminar el proceso Java, se elimina el proceso del Wrapper, WrapperManager se pondrá en modo de recuperación. El WrapperManager dentro del proceso Java reacciona a la pérdida del Wrapper asumiendo que el proceso Java se abandonó. Esto hace con que la JVM se apague correctamente 30 segundos después de que el proceso del Wrapper se elimina.

Sistema Bajo Alta Carga o Suspensión de Sistema

Hay casos en los que al Wrapper, la JVM o a ambos se les negará ciclos de CPU durante un período de tiempo prolongado. Esto puede suceder si un proceso poco amigable con los recursos comienza a ocupar el 100% de la CPU durante un período de tiempo. Esto también es posible si el usuario suspende el sistema a RAM o disco. Cuando se reanude el sistema, todas las aplicaciones que se estaban ejecutando habrán experimentado una pérdida de tiempo. El Wrapper es capaz de detectar que esto ha sucedido, por lo que es posible evitar hacer reinicios del proceso de la JVM que no sean necesarios. La siguiente salida muestra lo que sucede cuando el sistema se suspende a RAM por 255 segundos antes de reanudarse.

Salida de la Consola:
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Initializing...
jvm 1    | Wrapper (Version 3.x.x)
jvm 1    |
jvm 1    | start()
jvm 1    | JVM Process has not received any CPU time for 255 seconds.  Extending timeouts.
wrapper  | Wrapper Process has not received any CPU time for 255 seconds.  Extending timeouts.

A partir de la versión 3.1.0 del Wrapper, se agregó un nuevo mecanismo de temporizador que permite que el Wrapper maneje casos en los que se ejecuta en un estado de escasez de CPU de manera confiable porque el conteo de ticks se incrementa a una tasa que refleja la cantidad de CPU que se recibe, en lugar de ser absoluta. Esto significa que los tiempos de espera debido a cargas altas son muy poco probables. Solo asegúrese de que la propiedad wrapper.use_system_time esté configurada en FALSE para que el mecanismo de temporizador esté habilitado.

Ejecutar como un Servicio de Windows

Cuando se ejecuta como un servicio de Windows, la aplicación TestWrapper no podrá mostrar su interfaz de usuario. Esto le impide iniciar las pruebas descritas anteriormente. Sin embargo, podemos realizar algunas pruebas para verificar que el Wrapper actúa correctamente como un servicio de Windows.

Lo primero que se tiene que hacer es instalar la aplicación TestWrapper como un Servicio de Windows al ejecutar el siguiente comando:

Comando:
InstallTestWrapper-NT.bat
Salida de Datos:
wrapper  | TestWrapper Application installed.

Una vez instalada la aplicación TestWrapper como servicio, querremos iniciarla.

Comando:
net start TestWrapper
Salida de Datos:
The TestWrapper Application service is starting.
The TestWrapper Application service was started successfully.

El servicio se puede desinstalar ejecutando el siguiente comando:

UninstallTestWrapper-NT.bat
Si el servicio se está ejecutando, la salida de datos será:
wrapper  | Service is running.  Stopping it...
wrapper  | Waiting to stop...
wrapper  | TestWrapper Application stopped.
wrapper  | TestWrapper Application removed.

Si revisa el contenido de logs/wrapper.log, verá que la salida de datos es muy similar a la de la consola (excepto que, esta vez, el mensaje de inicio le informa que la aplicación se está iniciando como un servicio en lugar de como una consola).

wrapper.log
wrapper  | 2001/12/06 17:34:21 | --> Wrapper Started as Service
wrapper  | 2001/12/06 17:34:21 | Launching a JVM...
jvm 1    | 2001/12/06 17:34:22 | Initializing...
jvm 1    | 2001/12/06 17:34:22 | Wrapper (Version 3.x.x)
jvm 1    | 2001/12/06 17:34:22 |
jvm 1    | 2001/12/06 17:34:22 | start()

A continuación se muestran los resultados de varias acciones más que pueden realizarse en un Servicio de Windows:

Cierre y Reinicio de Sesión de Usuario

Se realiza una entrada de registro cuando el usuario cierra la sesión, pero el servicio no se ve afectado.

wrapper.log
wrapper  | 2001/12/06 17:39:39 | --> Wrapper Started as Service
wrapper  | 2001/12/06 17:39:40 | Launching a JVM...
jvm 1    | 2001/12/06 17:39:40 | Initializing...
jvm 1    | 2001/12/06 17:39:40 | Wrapper (Version 3.x.x)
jvm 1    | 2001/12/06 17:39:40 |
jvm 1    | 2001/12/06 17:39:41 | start()
wrapper  | 2001/12/06 17:40:07 | User logged out.  Ignored.
jvm 1    | 2001/12/06 17:40:07 | controlEvent(202)

Reiniciar la máquina

Esto generará una señal de cierre de sesión "logout" seguida de una señal de apagado "shutdown". El servicio se apagará sin problemas y luego se reanudará después de que se reinicie la máquina.

Una entrada de registro se realiza cuando el usuario cierra sesión, pero el servicio no se ve afectado.

wrapper.log
wrapper  | 2001/12/06 17:41:04 | --> Wrapper Started as Service
wrapper  | 2001/12/06 17:41:05 | Launching a JVM...
jvm 1    | 2001/12/06 17:41:05 | Initializing...
jvm 1    | 2001/12/06 17:41:05 | Wrapper (Version 3.x.x)
jvm 1    | 2001/12/06 17:41:05 |
jvm 1    | 2001/12/06 17:41:05 | start()
wrapper  | 2001/12/06 17:41:25 | User logged out.  Ignored.
jvm 1    | 2001/12/06 17:41:26 | controlEvent(202)
wrapper  | 2001/12/06 17:41:27 | Machine is shutting down.
jvm 1    | 2001/12/06 17:41:27 | controlEvent(203)
jvm 1    | 2001/12/06 17:41:28 | stop(0)
wrapper  | 2001/12/06 17:41:29 | <-- Wrapper Stopped
wrapper  | 2001/12/06 17:44:12 | --> Wrapper Started as Service
wrapper  | 2001/12/06 17:44:12 | Launching a JVM...
jvm 1    | 2001/12/06 17:44:17 | Initializing...
jvm 1    | 2001/12/06 17:44:21 | Wrapper (Version 3.x.x)
jvm 1    | 2001/12/06 17:44:21 |
jvm 1    | 2001/12/06 17:44:23 | start()

Por favor lea esta página para información detallada de cómo controlar el Wrapper como un Servicio de Windows.

Ejecutar como un Demonio en Unix

El Wrapper se puede iniciar usando el comando 'start' para que se ejecute en segundo plano. Si se inicia desde un terminal que no puede mostrar la GUI, la aplicación cambiará a modo consola, pero no será tan útil, ya que el Demonio no puede ser controlado con la consola.

Unix:
./testwrapper start

Una vez que se inicia la aplicación, la interfaz de usuario de la aplicación TestWrapper que se ejecuta como demonio se puede utilizar exactamente igual que cuando se ejecuta como una aplicación de consola.

Para detener las instancias del Wrapper que se ejecutan como un demonio, utilice el mismo script con el comando 'stop'.

Unix:
./testwrapper stop

Por favor lea esta página para una descripción completa de los comandos que se pueden utilizar para controlar el Wrapper mientras se ejecuta como un Demonio Unix.