|
|
 |
 |
| TestWrapper Application |
TestWrapper Application
 |
|
This section will make use of the TestWrapper sample application,
which is shipped with the Wrapper,
to demonstrate several of the Wrapper's failure recovery features.
 |
 |
|
Once you install the binary version of the Wrapper,
or have run build on the source version,
you will be ready to immediately run the sample application.
The TestWrapper sample application is also used to test
many of the recovery features of the Java Service Wrapper.
To run the example, go into your bin directory
and run the following script:
| Linux / Solaris: |
./testwrapper start
|
|
NOTE
|  |
The Solaris TestWrapper script
tries to write a PID file
to /var/run directory.
If you aren't logged in as a root user, this will fail.
You can fix this by simply changing
the PIDDIR variable in the script,
or by logging in as a root user.
If you log in as a root user, make sure that
you have appropriate permission to use the X server
or else you won't be able to see the TestWrapper GUI.
|
The Windows console can be stopped cleanly by pressing CTRL-C,
but the Linux and Solaris version require you to run the script
with the stop parameter:
| Linux / Solaris: |
./testwrapper stop
|
The Linux and Solaris versions also provide the ability to restart the application:
| Linux / Solaris: |
./testwrapper restart
|
When the application starts, you should see the following dialog:
You should also see the following in the console:
| Console Output: |
wrapper | --> Wrapper Started as Console
wrapper | Launching a JVM...
jvm 1 | Initializing...
jvm 1 | Wrapper (Version 3.x.x)
jvm 1 |
jvm 1 | start()
|
Let's start with the console output.
The first column of data displays the source of the output.
Lines starting with wrapper are
coming from the native Wrapper application.
Lines starting with jvm 1 are
coming from the output of the JVM.
The number after jvm indicates the JVM number
since the Wrapper was started.
We will see how that works when we start playing with the TestWrapper's dialog.
The console output is also all logged to
logs/wrapper.log.
The logged output differs from the console output in that each line of output also includes a timestamp.
| Output in the log file: |
wrapper | 2001/12/06 16:18:27 | --> Wrapper Started as Console
wrapper | 2001/12/06 16:18:28 | Launching a JVM...
jvm 1 | 2001/12/06 16:18:29 | Initializing...
jvm 1 | 2001/12/06 16:18:30 | Wrapper (Version 3.x.x)
jvm 1 | 2001/12/06 16:18:30 |
jvm 1 | 2001/12/06 16:18:30 | start()
|
The TestWrapper presents you with a number of buttons.
These are each used to test various functionality of the Wrapper.
Each button is described below with the output
you will see in the console if the button is activated.
|
 |
 |
|
This section will demonstrate how the Wrapper responds to various events.
Each of these events can be tested in the safety of your very own home
by pressing the various buttons on the TestWrapper's dialog.
 |
 |
|
Exits the JVM cleanly by calling WrapperManager.stop(0).
| Console Output: |
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
|
As you can see,
the application had its stop() method called
and was stopped cleanly.
|
 |
 |
|
This "Exit" button tests the Wrapper's ability to trap an unexpected call to
System.exit() and stop the application gracefully.
| Console Output: |
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
|
As an exercise, edit your conf/wrapper.conf
file and uncomment the property,
wrapper.disable_shutdown_hook=TRUE.
(Make sure to comment it back out when you are done)
Now rerun the TestWrapper.
| Console Output: |
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()
|
You will notice that the Wrapper no longer catches the call to
System.exit()
and so the it thinks that the JVM crashed and restarts it.
|
NOTE
|  |
Because Shutdown Hooks are not supported in Java version 1.2,
calls to System.exit
will always result in the JVM being restarted.
To shutdown the JVM using Java 1.2,
it is necessary to call WrapperManager.stop(exitCode).
|
|
 |
 |
|
This "Halt" button calls a very low-level method to stop the JVM very forcibly.
In this case, Shutdown Hooks are not executed and the Wrapper has no way to catch it.
| Console Output: |
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()
|
Notice that the Wrapper thinks that the JVM crashed and restarts it.
|
 |
 |
|
Restarts the JVM cleanly by calling
WrapperManager.restart()
| Console Output: |
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()
|
As you can see,
the application had its stop() method called
and was restarted cleanly.
|
 |
 |
|
This takes advantage of a bug in the 1.3 Sun JVM
to cause an immediate access violation in the JVM.
(It doesn't work in the IBM JVM. Or I guess you could say it does work...).
| Console Output (SUN JVM): |
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: Attempting to cause an access violation...
jvm 1 | #
jvm 1 | # HotSpot Virtual Machine Error, EXCEPTION_ACCESS_VIOLATION
jvm 1 | # Please report this error at
jvm 1 | # http://java.sun.com/cgi-bin/bugreport.cgi
jvm 1 | #
jvm 1 | # Error ID: 4F533F57494E13120E43505002D4
jvm 1 | #
jvm 1 |
jvm 1 | abnormal program termination
wrapper | JVM exited unexpectedly.
wrapper | Launching a JVM...
jvm 2 | Initializing...
jvm 2 | Wrapper (Version 3.x.x)
jvm 2 |
jvm 2 | start()
|
As you can see,
an access violation caused the JVM to display an error dump and then terminate.
The Wrapper immediately detects this and after a 5 second pause,
restarts the application in a new JVM,
as can be seen with the jvm 2.
All available information about the crash has been logged for future reference.
|
 |
 |
|
The Java Service Wrapper includes a lightweight native library
which is used to handle system events.
The library also contains a native method,
which is used for testing, to cause an access violation in native code due to a "NULL" reference.
Depending on the JVM, this will give different output.
In the example below, the JVM created a core dump which takes about a minute to save.
During this time, the JVM appears to be hung so the Wrapper kills and restarts it.
| Console Output: |
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: Attempting to cause an access violation...
jvm 1 | #
jvm 1 | # An EXCEPTION_ACCESS_VIOLATION exception has been detected in native code outside the VM.
jvm 1 | # Program counter=0x8f7105f
jvm 1 | #
wrapper | JVM is hung: Timed out waiting for signal from JVM.
wrapper | Java Virtual Machine 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()
|
|
 |
 |
|
This test causes the Wrapper to think that the JVM has become hung.
After 30 seconds, the Wrapper times out and decides that the JVM
will not come back and restarts it.
| Console Output: |
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 | Java Virtual Machine 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()
|
|
|
 |
 |
|
The above section covered all of the ways that an application can exit or
die of its own will. There are other external factors
that the Wrapper can also protect itself against.
 |
 |
|
Most Java applications die rather abruptly
if the user presses CTRL-C,
logs out of Windows, etc. You can work around some of these issues with a Shutdown Hook,
but the Wrapper implements this by using a native library to directly capture the system signals.
This makes it possible to have a Java application installed as a Windows Service
without it being stopped when a user logs out.
As a test, try pressing CTRL-C in the console (command window).
| Console Output: |
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
|
You can also see variations on this by logging out
when the console application is still running.
The Wrapper will correctly terminate the application.
| Console Output: |
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
|
On Linux or Solaris platforms,
you can only press CTRL-C
if the script used to launch the Wrapper was passed the console command.
If the Wrapper was launched using the
start command,
then it has been spawned in a different process as a service/daemon,
so you can't access the console.
To stop the spawned instances of the Wrapper,
run the same script used to launch the Wrapper,
only this time specify the stop command:
| Console Output: |
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
|
|
 |
 |
|
It is also possible, though unlikely,
that the application process could be killed by another application.
This test also simulates cases where the JVM dies very suddenly of its own accord.
On Unix systems,
you can kill the Java process with a kill -9 signal.
On Windows systems,
open up the Task Manager, and then select the Process tab.
After that, find the
java.exe process to kill and then kill it.
| Console Output: |
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()
|
The Wrapper will be restarted without any problems.
If rather than killing the Java process,
the Wrapper process is killed then there is currently now recovery mode.
The WrapperManager inside the Java process reacts to the loss of the Wrapper
by assuming that the Java process is abandoned.
This leads to the JVM being shutdown cleanly 30 seconds
after the Wrapper process died.
|
 |
 |
|
There are cases where either the Wrapper,
the JVM or both will be denied CPU cycles for an extended period of time.
This can happen
if a resource unfriendly process starts taking 100% of the CPU for a period of time.
It is also possible if the user Suspends the system to RAM or disk.
When the system is resumed, all running applications will have experienced some missing time.
The Wrapper is capable of recognizing that this has happened making it possible
to avoid unneeded restarts of the JVM process.
The following output shows what happens
when the System is suspended to RAM for 255 seconds before being resumed.
| Console Output: |
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.
|
|
|
 |
 |
|
When running as a Windows Service, the TestWrapper will be unable to show its Dialog.
So this sample application is not very interesting.
We can however do a few tests to verify
that the Wrapper acts as a Windows Service correctly.
The first thing you will need to do is get the TestWrapper application installed
as a Windows Service by running the following command:
| Command: |
InstallTestWrapper-NT.bat
|
| You will see the output: |
wrapper | Test Wrapper Application installed.
|
Once the TestWrapper application in installed as a service,
we will want to start it.
| Command: |
net start TestWrapper
|
| You will see the output: |
The Test Wrapper Application service is starting.
The Test Wrapper Application service was started successfully.
|
The service can be uninstalled by executing the following command:
UninstallTestWrapper-NT.bat
|
| If the service is running, you will see the output: |
wrapper | Service is running. Stopping it...
wrapper | Waiting to stop...
wrapper | Test Wrapper Application stopped.
wrapper | Test Wrapper Application removed.
|
If you look at the contents of logs/wrapper.log,
you will see output very similar to that of the console.
Except this time,
the start message informs you that the application is being started as a service.
| 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()
|
Here are the results of several more actions that can take place on Windows Service:
 |
 |
|
A log entry is made when the user logs out, but the service is unaffected.
| 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)
|
|
 |
 |
|
This will result in a logout signal followed by a shutdown signal.
The service will be shutdown gracefully and then come back after the machine restarts.
A log entry is made when the user logs out, but the service is unaffected.
| 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()
|
|
|
 |
 |
|
There are not any differences between running
as a service vs as a console application in a Unix environment.
|
|
|
|
 | If you notice something that is incorrect, missing, or simply feel that some part of this page could be explained better, feel free to log in and add a comment. You will need to register before you can log on. |
|
|  |
|
 |
| |