|
From: Martin V. <ma...@ja...> - 2003-01-20 14:31:11
|
Hi,
We're running a web application (a multiplayer game) on the JBoss
application server under Windows 2000.
I've been able to successfully run our application in the Wrapper's console
mode using Sun's VM, but it doesn't work with JRockit. The Wrapper version
is 2.2.9.
It looks like the Wrapper kills the application when the first thread that
was started ends. Here's a test application that reproduces the problem:
public class TestStart implements Runnable {
private static Thread thread;
static TestStart instance;
public static void main(String[] args) {
System.out.println("TestStart: starting thread");
instance = new TestStart();
thread = new Thread(instance, "TestStart thread");
thread.start();
System.out.println("TestStart: main ending");
}
public void run() {
System.out.println("Thread starting");
while(!Thread.interrupted()) {
System.out.println("Running...");
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
break;
}
}
System.out.println("Thread ending");
}
public void stop() {
System.out.println("Stopping thread");
thread.interrupt();
try {
thread.join();
}
catch(InterruptedException e) {
System.out.println("Interrupted waiting for thread to die");
}
System.out.println("Thread stopped");
}
}
#********************************************************************
# Wrapper parameters
#********************************************************************
# Java Application
#wrapper.java.command=/j2sdk1.4.0_01/bin/java
wrapper.java.command=/jrockit/7.0/1.4.0/bin/java
# Java Main class
wrapper.java.mainclass=com.silveregg.wrapper.WrapperStartStopApp
# Java Classpath (include wrapper.jar) Add class path elements as
# needed starting from 1
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=<path to TestStart.class and TestStop.class>
# Java Library Path (location of Wrapper.DLL or libwrapper.so)
wrapper.java.library.path.1=../lib
# Java Additional Parameters
#wrapper.java.additional.1=
# Initial Java Heap Size (in MB)
wrapper.java.initmemory=64
# Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=512
# Application parameters. Add parameters as needed starting from 1
wrapper.app.parameter.1=TestStart
wrapper.app.parameter.2=0
wrapper.app.parameter.3=TestStop
wrapper.app.parameter.4=true
wrapper.app.parameter.5=0
# Port which the native wrapper code will attempt to connect to
wrapper.port=1777
#********************************************************************
# Wrapper Logging parameters
#********************************************************************
# Format of output for the console. (See docs for formats)
wrapper.console.format=PM
# Log Level for console output. (See docs for log levels)
wrapper.console.loglevel=DEBUG
# INFO
# Log file to use for wrapper output logging.
wrapper.logfile=../logs/wrapper.log
# Format of output for the log file. (See docs for formats)
wrapper.logfile.format=LPTM
# Log Level for log file output. (See docs for log levels)
wrapper.logfile.loglevel=INFO
# Maximum size that the log file will be allowed to grow to before
# the log is rolled. Size is specified in bytes. The default value
# of 0, disables log rolling. May abbreviate with the 'k' (kb) or
# 'm' (mb) suffix. For example: 10m = 10 megabytes.
wrapper.logfile.maxsize=10m
# Maximum number of rolled log files which will be allowed before old
# files are deleted. The default value of 0 implies no limit.
wrapper.logfile.maxfiles=2
# Log Level for sys/event log output. (See docs for log levels)
wrapper.syslog.loglevel=NONE
#********************************************************************
# Wrapper Unix daemon parameters
#********************************************************************
# File to write process ID to
wrapper.pidfile=/var/run/testwrapper.pid
#********************************************************************
# Wrapper NT Service parameters
#********************************************************************
# WARNING - Do not modify any of these parameters when an application
# using this configuration file has been installed as a service.
# Please uninstall the service before modifying this section. The
# service can then be reinstalled.
# Name of the service
wrapper.ntservice.name=WrapperTest
# Display name of the service
wrapper.ntservice.displayname=WrapperTest
# Description of the service
wrapper.ntservice.description=WrapperTest
# Service dependencies. Add dependencies as needed starting from 1
wrapper.ntservice.dependency.1=
# Mode in which the service is installed. AUTO_START or DEMAND_START
wrapper.ntservice.starttype=AUTO_START
# Priority at which the service is run. NORMAL, LOW, HIGH, or
# REALTIME
wrapper.ntservice.process_priority=NORMAL
Here's the output when I run this using Sun's VM:
wrapper | --> Wrapper Started as Console
wrapperp | server listening on port 1777.
wrapper | Launching a JVM...
wrapper | command:
"/j2sdk1.4.0_01/bin/java" -Xms64m -Xmx512m -Djava.library.path="../lib" -cla
sspath
"../lib/wrapper.jar;c:/proj/wrapper_2.2.9_src/build/classes" -Dwrapper.key="
jX9U1ZfVr5KS3Ln6" -Dwrapper.port=1777 -Dwrapper.debug="TRUE" -Dwrapper.cpu.t
imeout="10" -Dwrapper.jvmid=1 com.silveregg.wrapper.WrapperStartStopApp
TestStart 0 TestStop true 0
wrapper | Java Virtual Machine started (PID=320)
jvm 1 | Wrapper Manager: JVM #1
jvm 1 | Wrapper Manager: Registering shutdown hook
jvm 1 | Wrapper Manager: Using wrapper
jvm 1 | Calling native initialization method.
jvm 1 | Initializing WrapperManager native library.
jvm 1 | Java Executable: C:\j2sdk1.4.0_01\bin\java.exe
jvm 1 | Java Version : 1.4.0_01-b03 Java HotSpot(TM) Client VM
jvm 1 | Java VM Vendor : Sun Microsystems Inc.
jvm 1 |
jvm 1 | Wrapper (Version 2.2.9)
jvm 1 |
jvm 1 | Open socket to wrapper...
jvm 1 | Opened Socket
jvm 1 | Send a packet 110 : jX9U1ZfVr5KS3Ln6
jvm 1 | handleSocket(Socket[addr=/127.0.0.1,port=1777,localport=1759])
wrapperp | accepted a socket from 127.0.0.1 on port 1759
wrapperp | read a packet 110 : jX9U1ZfVr5KS3Ln6
wrapper | Got key from JVM: jX9U1ZfVr5KS3Ln6
wrapperp | sent 3 bytes
wrapper | Start Application.
wrapperp | sent 7 bytes
jvm 1 | Received a packet 112 : 1
jvm 1 | Wrapper Manager: LowLogLevel from Wrapper is 1
jvm 1 | Received a packet 100 : start
jvm 1 | calling listener.start()
jvm 1 | WrapperStartStopApp: start(args)
jvm 1 | WrapperStartStopApp: invoking start main method
jvm 1 | TestStart: starting thread
jvm 1 | TestStart: main ending
jvm 1 | WrapperStartStopApp: start main method completed
jvm 1 | WrapperStartStopApp: start(args) end. Main Completed=true,
exitCode=null
jvm 1 | returned from listener.start()
jvm 1 | Send a packet 106 :
jvm 1 | Thread starting
jvm 1 | Running...
wrapperp | read a packet 106 :
wrapper | JVM signalled that it was started.
jvm 1 | Running...
jvm 1 | Running...
wrapperp | sent 6 bytes
jvm 1 | Received a packet 103 : ping
jvm 1 | Send a packet 103 : ok
wrapperp | read a packet 103 : ok
wrapper | Got ping response from JVM
jvm 1 | Running...
jvm 1 | Running...
jvm 1 | Running...
jvm 1 | Running...
Here's the output when using the JRockit VM. Note that the Wrapper says "All
non-daemon threads have stopped. Exiting." although our application has
started a thread.
wrapper | --> Wrapper Started as Console
wrapperp | server listening on port 1777.
wrapper | Launching a JVM...
wrapper | command:
"/jrockit/7.0/1.4.0/bin/java" -Xms64m -Xmx512m -Djava.library.path="../lib"
-classpath
"../lib/wrapper.jar;c:/proj/wrapper_2.2.9_src/build/classes" -Dwrapper.key="
kfsaRmxpL4OAxFrM" -Dwrapper.port=1777 -Dwrapper.debug="TRUE" -Dwrapper.cpu.t
imeout="10" -Dwrapper.jvmid=1 com.silveregg.wrapper.WrapperStartStopApp
TestStart 0 TestStop true 0
wrapper | Java Virtual Machine started (PID=1404)
jvm 1 | Wrapper Manager: JVM #1
jvm 1 | Wrapper Manager: Registering shutdown hook
jvm 1 | Wrapper Manager: Using wrapper
jvm 1 | Calling native initialization method.
jvm 1 | Initializing WrapperManager native library.
jvm 1 | Java Executable: C:\jrockit\7.0\1.4.0\bin\java.exe
jvm 1 | Java Version : 1.4.0 BEA Weblogic JRockit(R) Virtual Machine
jvm 1 | Java VM Vendor : BEA Systems, Inc.
jvm 1 |
jvm 1 | Wrapper (Version 2.2.9)
jvm 1 |
jvm 1 | Open socket to wrapper...
jvm 1 | Opened Socket
jvm 1 | Send a packet 110 : kfsaRmxpL4OAxFrM
jvm 1 | handleSocket(Socket[addr=/127.0.0.1,port=1777,localport=1760])
wrapperp | accepted a socket from 127.0.0.1 on port 1760
wrapperp | read a packet 110 : kfsaRmxpL4OAxFrM
wrapper | Got key from JVM: kfsaRmxpL4OAxFrM
wrapperp | sent 3 bytes
wrapper | Start Application.
wrapperp | sent 7 bytes
jvm 1 | Received a packet 112 : 1
jvm 1 | Wrapper Manager: LowLogLevel from Wrapper is 1
jvm 1 | Received a packet 100 : start
jvm 1 | calling listener.start()
jvm 1 | WrapperStartStopApp: start(args)
jvm 1 | WrapperStartStopApp: invoking start main method
jvm 1 | TestStart: starting thread
jvm 1 | TestStart: main ending
jvm 1 | WrapperStartStopApp: start main method completed
jvm 1 | WrapperStartStopApp: start(args) end. Main Completed=true,
exitCode=null
jvm 1 | returned from listener.start()
jvm 1 | Send a packet 106 :
jvm 1 | Thread starting
jvm 1 | Running...
wrapperp | read a packet 106 :
wrapper | JVM signalled that it was started.
wrapperp | sent 6 bytes
jvm 1 | Received a packet 103 : ping
jvm 1 | Send a packet 103 : ok
jvm 1 | All non-daemon threads have stopped. Exiting.
jvm 1 | Send a packet 101 : 0
wrapperp | read a packet 103 : ok
wrapper | Got ping response from JVM
wrapperp | read a packet 101 : 0
wrapper | JVM requested a shutdown. (0)
wrapper | wrapperStopProcess(0) called.
wrapper | Sending stop signal to JVM
wrapperp | sent 2 bytes
jvm 1 | Running...
jvm 1 | Thread, Wrapper-Connection, handling the shutdown process.
jvm 1 | calling listener.stop()
jvm 1 | WrapperStartStopApp: stop(0)
jvm 1 | WrapperStartStopApp: invoking stop main method
jvm 1 | TestStop: main
jvm 1 | Stopping thread
jvm 1 | Thread ending
jvm 1 | Thread stopped
jvm 1 | TestStop: main ending
jvm 1 | WrapperStartStopApp: stop main method completed
jvm 1 | returned from listener.stop()
jvm 1 | Send a packet 107 : 0
jvm 1 | Closing socket.
wrapperp | read a packet 107 : 0
wrapper | JVM signalled that it was stopped.
wrapperp | socket read no code (closed?).
jvm 1 | calling System.exit(0)
wrapper | JVM exited normally.
wrapper | <-- Wrapper Stopped
The problem seems to be in the following code in WrapperManager:
private static void checkThreads() {
int liveCount = getNonDaemonThreadCount();
// There will always be one non-daemon thread alive. This thread is
either the main
// thread which has not yet completed, or a thread launched by java when
the main
// thread completes whose job is to wait around for all other non-daemon
threads to
// complete. We are overriding that thread here.
if (liveCount <= 1) {
if (_debug) {
System.out.println("All non-daemon threads have stopped. Exiting.");
}
// Exit normally
WrapperManager.stop(0);
// Will not get here.
} else {
// There are daemons running, let the JVM continue to run.
}
}
The first comment here might be the key. Perhaps the assumption that there's
always one non-daemon thread alive is JVM specific. I've tried a workaround
to create a dummy thread, making sure that the thread count never falls
below 2. It works, but it would be nice with a cleaner solution.
Any ideas?
Martin Vilcans
|