Edit: It seems my test to determine whether the original JVM had exited was flawed to begin with (see comments on accepted answer). Sorry for the noise.
I have a need to have a running JVM start another JVM and then exit. I'm currently trying to do this via Runtime.getRuntime().exec()
. The other JVM starts, but my original JVM won't exit until the "child" JVM process stops. It appears that using Runtime.getRuntime().exec()
creates a parent-child relationship between the processes. Is there some way to de-couple the spawned process so that the parent can die, or some other mechanism to spawn a process without any relationship to the creating process?
Note that this seems exactly like this question: http://stackoverflow.com/questions/2566502/using-java-to-spawn-a-process-and-keep-it-running-after-parent-quits but the accepted answer there doesn't actually work, at least not on my system (Windows 7, Java 5 and 6). It seems that maybe this is a platform-dependent behavior. I'm looking for a platform independent way to reliably invoke the other process and let my original process die.
For example, suppose I have a jar file at C:\myjar.jar
and I want to run the class com.example.RunMe
that lives in that jar. Lets say that class pops up a JOptionPane, and then exits once the user has hit OK.
Now, the following is the program running in JVM #1:
public static void main(String[] args) {
String javaHome = System.getProperty("java.home");
String os = System.getProperty("os.name");
String javawBin = javaHome + File.separator + "bin" + File.separator + "javaw";
if (os.toLowerCase().contains("win")) {
javawBin += ".exe";
}
List<String> cmd = new ArrayList<String>();
cmd.add("\"" + javawBin + "\"");
cmd.add("-cp");
cmd.add("\"C:\\myjar.jar\"");
cmd.add("com.example.RunMe");
System.out.println("Running: " + cmd);
try {
System.out.println("Launching...");
Process p = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
new Thread(new StreamGobbler(p.getInputStream())).start();
new Thread(new StreamGobbler(p.getErrorStream())).start();
System.out.println("Launched JVM.");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
private static class StreamGobbler implements Runnable {
InputStream stream;
StreamGobbler(InputStream stream) {
this.stream = stream;
}
public void run() {
byte[] buf = new byte[64];
try {
while (stream.read(buf) != -1)
;
} catch (IOException e) {
}
}
}
The observed behavior is that both "Launching..." and "Launched JVM." are printed, but JVM #1 only exits after you hit OK in the JOptionPane launched by JVM #2. Also - the behavior is the same whether or not you start up the stream gobbler threads or not.
Also, to save someone the breath, yes I know I could create a new URLClassLoader with that jar file and run it that way, but thats not what I'm trying to do here.