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

使用Java,我可以让一个JVM派生另一个JVM,然后让原来的JVM退出吗?,java,process,Java,Process,编辑:我的测试似乎是为了确定原始JVM是否已退出,但从一开始就存在缺陷(请参阅接受答案上的评论)。很抱歉听到这样的噪音 我需要让一个正在运行的JVM启动另一个JVM,然后退出。我目前正试图通过Runtime.getRuntime().exec()实现这一点。另一个JVM启动,但在“子”JVM进程停止之前,我的原始JVM不会退出。似乎使用Runtime.getRuntime().exec()会在进程之间创建父子关系。是否有某种方法来解除派生进程的耦合,以便父进程可以死亡,或者有某种其他机制来派生与

编辑:我的测试似乎是为了确定原始JVM是否已退出,但从一开始就存在缺陷(请参阅接受答案上的评论)。很抱歉听到这样的噪音

我需要让一个正在运行的JVM启动另一个JVM,然后退出。我目前正试图通过
Runtime.getRuntime().exec()
实现这一点。另一个JVM启动,但在“子”JVM进程停止之前,我的原始JVM不会退出。似乎使用
Runtime.getRuntime().exec()
会在进程之间创建父子关系。是否有某种方法来解除派生进程的耦合,以便父进程可以死亡,或者有某种其他机制来派生与创建进程没有任何关系的进程

请注意,这似乎与这个问题完全相同:但公认的答案实际上不起作用,至少在我的系统(Windows7、Java5和Java6)上不起作用。这似乎是一种依赖于平台的行为。我正在寻找一种独立于平台的方法来可靠地调用另一个进程,让我的原始进程消亡

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

下面是在JVM#1中运行的程序:

publicstaticvoidmain(字符串[]args){
字符串javaHome=System.getProperty(“java.home”);
字符串os=System.getProperty(“os.name”);
字符串javawBin=javaHome+File.separator+“bin”+File.separator+“javaw”;
if(os.toLowerCase().contains(“win”)){
javawBin+=“.exe”;
}
List cmd=new ArrayList();
cmd.add(“\”+javawBin+“\”);
cmd.添加(“-cp”);
cmd.add(“\”C:\\myjar.jar\”);
cmd.add(“com.example.RunMe”);
System.out.println(“运行:+cmd”);
试一试{
System.out.println(“启动…”);
进程p=Runtime.getRuntime().exec(cmd.toArray(新字符串[cmd.size()]);
新线程(新的StreamGobbler(p.getInputStream()).start();
新线程(新的StreamGobbler(p.getErrorStream()).start();
System.out.println(“启动的JVM”);
系统出口(0);
}捕获(IOE异常){
e、 printStackTrace();
}
}
私有静态类StreamGobbler实现可运行{
输入流;
StreamGobbler(输入流){
this.stream=流;
}
公开募捐{
字节[]buf=新字节[64];
试一试{
while(stream.read(buf)!=-1)
;
}捕获(IOE异常){
}
}
}
观察到的行为是,“Launching…”和“Launched JVM.”都会被打印出来,但是JVM#1只有在您在JVM#2启动的JOptionPane中点击OK后才会退出。另外-无论是否启动流吞噬器线程,行为都是相同的


另外,为了让某人省心,是的,我知道我可以用jar文件创建一个新的URLClassLoader并以这种方式运行它,但这不是我在这里要做的。

据我所知,杀死一个进程通常会杀死所有子进程。我怀疑是否有一种独立于平台的方法可以做到这一点。

Windows没有像Unix系统那样在进程之间建立同样的父子关系。您的父进程可能没有退出,因为其中仍有线程在运行。此线程可能正在等待子进程终止,这可以解释为什么父进程在子进程退出时退出。

我刚刚尝试了以下代码,我看到进程正在生成,主进程在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){}
    }
}

运行
StreamGobblers
的线程位于进程#1内,并且不是守护进程线程,因此进程#1在这些线程完成之前不会结束,当它们所占用的流随着进程#2结束而消失时


去掉创建这些线程的两行。

2件事:1)一个进程是否可以生成另一个独立的进程,而不是子进程?2)我根本不能杀死父母。System.exit(0)将挂起,直到子进程停止。父进程挂起System.exit(0)。这难道不会阻止等待线程完成吗?另外,在Win7中仍然是这样吗?@CarlG:挂起
系统。退出(0)
肯定是意外的。我不认为Windows7中进程终止的语义发生了变化,但我想它们可能发生了变化。我很想知道这个问题的最终解决方案是什么。这是我的第一直觉,但我认为System.exit(0)应该负责运行线程。但是阅读Runtime.exit文档,我想知道不同的错误代码是否会导致不同的行为。这是合理的,但正如我上面指出的,去掉这两行代码没有任何效果。对,对不起。调用
System.exit(0)
处理这些线程。我认为你是对的。事情是这样的。我检查JVM#1是否已退出的晴雨表是Eclipse控制台中的红色“停止”按钮是否处于活动状态,因为这是过去JVM寿命的可靠指示器。然而,Windows任务管理器向我展示了一个不同的故事,即JVM#1确实像预期的那样立即退出。那么,eclipse停止按钮将如何绑定到子进程?也许eclipse不理解System.exit?eclipse所做的只是生成javaw.exe本身。一定有某种联系,它就在那里?但奇怪的是,它从任务管理器中消失了。也许我是小题大做了。Eclipse也会利用
控制台
(它注册了一个关闭钩子)来干扰输入/输出。是的,我一直在直接使用命令行使用实际的jar版本来测试它,它似乎工作得很好。对不起,大家吵闹了。
public class Test {
    public static void main(String[] args) throws Exception {
        if(args.length == 0)
            Runtime.getRuntime().exec("javaw Test loop");
        else
            while(true){}
    }
}