A small library for creating (and killing!) Java processes
This is a small library to help you create and (automatically kill) Java processes from
within Java. This is useful in a number of situations:
To start part of your Java program in a separate JVM, simply write:
Process proc = new JavaProcessBuilder(SomeClass.class, "some", "args").start();
That’s it! This snippet will start a new JVM with SomeClass
as the main class, passing"some"
and "args"
as arguments. No need to specify the classpath, the VM args, or
the path to the Java executable; these are all taken from the JVM in which your program
is running!
JavaProcessBuilder
makes it very simple to configure the classpath, the VM args, or
the Java executable, if you want them to be different from those of the parent JVM:
Process proc = new JavaProcessBuilder(SomeClass.class)
.javaHome("/different/java/")
.classpath("some-classes.jar")
.vmArgs("-ea", "-Xmx8g")
.start();
If you know the ProcessBuilder
class from the Java Standard Library, you may also know that lets you specify a number
of additional options when starting a process, such as environment variables, working
directory, or I/O behavior. JavaProcessBuilder
is actually built on top ofProcessBuilder
, so you can configure all of these things too:
Process proc = new JavaProcessBuilder(SomeClass.class)
.classpath("some-classes.jar")
.build()
.directory(new File("test"))
.inheritIO()
.start();
What is happening here is that build()
returns a ProcessBuilder
instance that
has all the JVM-specific configuration imprinted and can then be further configured.
In fact, the JavaProcessBuilder.start()
method is simply a shorthand forbuild().start()
.
One thing that is annoying when executing parts of your program in separate JVMs is
that they continue to run when you kill the parent process (especially during
debugging). This library comes with two mechanism that can help you with that.
The first mechanism is based on
shutdown hooks
and can be used in the following way:
new AutoProcessKiller().add(process);
Now, when the JVM shuts down, the AutoProcessKiller
(which is a Thread) is executed
and kills the process (if it is still running).
However, this will not work if the JVM is terminated forcibly, which happens, for
example, if you press the stop button in Eclipse. In this case, the shutdown hooks
may not be executed, so the child processes may continue to run. In fact, I think
any mechanism to kill child processes from within the parent JVM is doomed to
suffer from this problem.
This is why this library comes with a second mechanism, which works from within the
child VM and is guaranteed to kill the child process as soon as the parent process
stops running (for whatever reason). You can use it by calling
AutoExit.install();
in the child VM. Or, to make it even simpler, you can call autoExit(true)
on the
process builder instance that you use to start the child VM:
Process proc = new JavaProcessBuilder(SomeClass.class).autoExit(true).start();
In this case, the process builder will use the AutoExitProgram
class as the actual
main class, which in turn calls AutoExit.install()
and then calls SomeClass.main()
.
This mechanism is based on a simple trick: AutoExit
(being a separate thread) callsSystem.in.read()
, which only returns once the parent process terminates. As soon as
this happens, System.exit()
is called. Note, however, that this trick does not work
if you need to use System.in
for something else in the child process. In that case,
you should use the first mechanism.