使用Java,我可以让一个JVM产生另一个JVM,然后让原始的一个退出吗?

Car*_*rlG 12 java process

编辑:似乎我的测试,以确定原始JVM是否已退出是有缺陷的开始(见接受答案的评论).对不起噪音.

我需要有一个正在运行的JVM启动另一个JVM然后退出.我正在尝试这样做Runtime.getRuntime().exec().另一个JVM启动,但我的原始JVM将不会退出,直到"子"JVM进程停止.似乎使用Runtime.getRuntime().exec()在进程之间创建父子关系.是否有某种方法可以解除生成的进程以使父进程死亡,或者某种其他机制来生成进程而与创建进程没有任何关系?

请注意,这看起来与此问题完全相同:使用Java生成进程并在父进程退出后继续运行,但是接受的答案实际上并不起作用,至少在我的系统上没有(Windows 7,Java 5和6).似乎这可能是一个依赖于平台的行为.我正在寻找一种独立于平台的方法来可靠地调用其他进程并让我的原始进程死掉.

例如,假设我有一个jar文件,C:\myjar.jar我想运行该com.example.RunMejar中的类.假设该类弹出一个JOptionPane,然后在用户点击OK后退出.

现在,以下是在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) {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

观察到的行为是"启动......"和"启动JVM".打印,但JVM#1仅在您通过JVM#2启动的JOptionPane中的OK之后退出.此外 - 无论您是否启动流gobbler线程,行为都是相同的.

另外,为了节省一些人的呼吸,是的,我知道我可以使用该jar文件创建一个新的URLClassLoader并以这种方式运行,但这不是我在这里尝试做的.

yka*_*ich 4

我刚刚尝试了以下代码,我看到进程正在生成,并且主进程在 Vista 和 Java 6 上退出。我认为您的代码可能还存在其他问题。

public class Test {
    public static void main(String[] args) throws Exception {
        if(args.length == 0)
            Runtime.getRuntime().exec("javaw Test loop");
        else
            while(true){}
    }
}
Run Code Online (Sandbox Code Playgroud)