Example of redirecting standard out and err of a spawned Process.
The inability to capture a Java thread dump when a JVM is run detached
from a terminal makes troubleshooting issues difficult. I have spent a
good deal of time trying to
force a Java thread dump through the swawned application code but found
it is
not possible though the API -- when a JVM receives a SIGQUIT signal it
will produce a
thread dump to the Unix-level standard out (file descriptor 1). The
only way to capture the dump is to redirect standard out when the Port
Monitor process is launched. The parent process is
doing a Runtime.getRuntime().exec()
to spawn a child process. In order to capture the OS-level
standard out and error the sub-process needs to be launched similar to
this:
Process process = Runtime.getRuntime().exec(command);
ProcessLogger errorStream = new ProcessLogger(process
.getErrorStream(), new FileOutputStream("stderr.log"),
"stderr.log");
ProcessLogger outputStream = new ProcessLogger(process
.getInputStream(), new FileOutputStream("stdout.log"),
"stdout.log");
The ProcessLogger class just takes the input stream and writes
it out to a file. It could just as easily write out to a log4j Appender
but I wanted the sample code as simple as possible.
I created a jar name process.jar with three
class files and included the source for your own enjoyment.
Run it on a *nix box::
java ParentProcess
ParentProcess exec's SubProcess and redirects SubProcess'
standout
output and error streams to files "stdout.log" and "stderr.log" using a
simple Logger. The SubProcess
redirects it's System.out and
System.err to the file "application.log" and recursively calls a
method,
outputting a count once per second.
do a
ps -ef | grep ProcessWorker
and note PID. Next do a
kill -QUIT <pid>
and a Java thread dump should output to the "stdout.log" file.