It seems that this is not a bug.
In 1.1.x, runtime.exec create a new process which is a detached process, so the
child process will not accept signals (like ctrl+break) from the console of the
parent process. That's why in 1.1.x, there's no thread dump.
In 1.2.2, runtime.exec create a new attached process, the child process can
still accept the signal from the console of the parent process, it's stderr is
linked to the parent's pipe. After it received the signal, it sent out thread
dump to stderr which redirects to the pipe, as the pipe has a limited capacity,
another thread needs to read from the pipe to keep it going, otherwise,
the child process appears hang.
The evaluation above is incorrect; a corrected one follows. A solution
exists for this problem; please see the end of this evaluation for it.
The problem was caused by the addition of the shutdown hook mechanism
to 1.3. Shutdown hooks, compared to the System.runFinalizersOnExit()
mechanism, have stronger guarantees regarding when they are run; for
example, if the VM is terminated by a Ctrl-C, finalizers will not be
executed via runFinalizersOnExit, but shutdown hooks will be run.
On Win32, shutdown hooks are implemented by adding a console control
handler (see the documentation for SetConsoleCtrlHandler) which, upon
seeing a condition like a Control-C or a "user logoff event", raises
the termination condition in the VM. This causes the shutdown hooks to
Both the shutdown hook mechanism and the Ctrl-Break stack dump require
signal-like information. 1.2 implemented the Ctrl-Break stack dump
using the POSIX "signal" call on Win32. It turns out (as was noted in
the 1.3 VM code by hong.zhang@eng) that this mechanism translates all
console events except Ctrl-C into SIGBREAK, which is not sufficient
granularity to support both Ctrl-Break and shutdown hooks. This is why
the console control handler was added in 1.3.
When the VM's console handler receives the CTRL_LOGOFF_EVENT, it
informs the rest of the VM of pending termination (thereby causing
shutdown hooks to be run) and returns TRUE. According to the MSDN
documentation, a return value of TRUE for this event will cause the
popup window for process termination to be displayed. It seems that
this return value was chosen because the VM is still doing work
(running the shutdown hooks asynchronously) after the
CTRL_LOGOFF_EVENT is received, and the author thought that returning
false would cause the VM to be terminated by the OS while doing this
work (as is stated in the MSDN documentation: the system's default
handler terminates the process).
The MSDN documentation is not specific about the relationship between
services and the CTRL_LOGOFF_EVENT. Conceptually, a service runs in
the background and should not be associated with any particular user's
login session, so one might expect that a service should not be
notified of logoff events. However, Win32 does send these events to
services. Interestingly, the default console handler for services
differs from the default for ordinary console processes; services
continue to run after their default handler executes. This is what
allows ordinary programs (which either do not install a console
handler, or which return FALSE in their console handler for
CTRL_LOGOFF_EVENT) to work with, for example, ServiceInstaller.
However, it does not seem that there is a way for a process to query
whether it is running as a service. If there were, the correct
behavior for the VM upon receiving the CTRL_LOGOFF_EVENT if it were
running as a service would be to skip running the shutdown hooks, not
signal the termination condition to the rest of the VM, and return
FALSE. Otherwise, the two possible workarounds are either to provide
another command line option to java.exe ("running as a service on
Windows NT") or to somehow intercept the CTRL_LOGOFF_EVENTs at the
service wrapper level.
Since the time this bug was filed, its original submitter (who is the
author of ServiceInstaller) has released a revised piece of software,
called JavaServ, which solves this problem elegantly by using the JNI
Invocation API to create a Java VM and installing a console control
handler afterwards which intercepts the CTRL_LOGOFF_EVENT and prevents
it from being passed to the VM. It also contains other useful features
like allowing pure Java programs to receive service control events.
JavaServ may be downloaded from
The comments on the JDC also contain the source code to a similar
Since the time the above evaluation was written, other problems have
been discovered on Unix platforms involving the interaction between
the signals/events the VM now catches to implement the shutdown hook
mechanism and application code which may rely on catching those
signals; see bug 4345157 and related bugs. It was agreed that it is
necessary to have a cross-platform mechanism to inform the VM that the
user will take care of calling shutdown hooks (by calling
System.exit()), but because he/she either needs to catch SIGINT or
similar signals on Unix or run the VM as a service on NT, the VM must
not install signal handlers or attempt to catch console control
events. It appears that similar reasoning informed the addition of the
-Xrs flag in the Classic VM.
The -Xrs flag has been reused to support this functionality; if it is
specified on Windows NT, for example, java.exe can again be run with
the ServiceInstaller wrapper (http://www.kcmultimedia.com/smaster/).
This fix will appear in 1.3.1 and be documented in the README.