小编典典

如何从Java程序启动完全独立的进程?

java

我正在开发一个用Java编写的程序,对于某些操作,它使用用户配置的命令行启动外部程序。当前它使用Runtime.exec()并且不保留Process引用(启动的程序是文本编辑器或存档实用程序,因此不需要系统输入/输出/错误流)。

但是,这有一个小问题,即当Java程序退出时,直到所有启动的程序都退出后,它才真正退出。

如果启动的程序完全独立于启动它们的JVM,我将更喜欢它。

目标操作系统是多个,最低要求是Windows,Linux和Mac,但是真正需要的是带有JVM的任何GUI系统(因此用户可以配置实际的命令行)。

有谁知道如何使启动的程序完全独立于JVM执行?

编辑以回应评论

启动代码如下。该代码可以启动位于特定行和列的编辑器,也可以启动档案查看器。在配置的命令行中,将引号值视为ECMA-262编码,然后对其进行解码,并去除引号以形成所需的exec参数。

启动发生在EDT上。

static Throwable launch(String cmd, File fil, int lin, int col) throws Throwable {
    String frs[][]={
        { "$FILE$"  ,fil.getAbsolutePath().replace('\\','/') },
        { "$LINE$"  ,(lin>0 ? Integer.toString(lin) : "") },
        { "$COLUMN$",(col>0 ? Integer.toString(col) : "") },
        };
    String[] arr; // array of parsed tokens (exec(cmd) does not handle quoted values)

    cmd=TextUtil.replace(cmd,frs,true,"$$","$");
    arr=(String[])ArrayUtil.removeNulls(TextUtil.stringComponents(cmd,' ',-1,true,true,true));
    for(int xa=0; xa<arr.length; xa++) {
        if(TextUtil.isQuoted(arr[xa],true)) {
            arr[xa]=TextDecode.ecma262(TextUtil.stripQuotes(arr[xa]));
            }
        }
    log.println("Launching: "+cmd);
    Runtime.getRuntime().exec(arr);
    return null;
    }

仅当从我的IDE启动该程序时,这似乎才发生。由于问题仅存在于我的开发环境中,因此我将结束这个问题。在生产中这不是问题。根据测试程序的答案之一,以及我进行的进一步测试,我很满意,这个问题不会在任何平台上被该程序的任何用户看到。


阅读 717

收藏
2020-03-16

共2个答案

小编典典

如果你发布一个重现问题所需的最少代码的测试部分,则可能会有所帮助。我在Windows和Linux系统上测试了以下代码。

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        Runtime.getRuntime().exec(args[0]);
    }
}

并在Linux上进行了以下测试:

java -jar JustForTesting.jar /home/monceaux/Desktop/__TMP/test.sh

test.sh如下所示:

#!/bin/bash
ping -i 20 localhost

在Linux上也是如此:

java -jar JustForTesting.jar gedit

并在Windows上对此进行了测试:

java -jar JustForTesting.jar notepad.exe

所有这些都启动了预期的程序,但是Java应用程序没有问题。我报告了以下版本的Sun JVM java -version:

  • Windows:1.6.0_13-b03
  • Linux:1.6.0_10-b33

我还没有机会在Mac上进行测试。可能与你项目中的其他代码发生了一些交互作用,可能还不清楚。你可能需要尝试此测试应用程序,然后查看结果。

2020-03-16
小编典典

你的流程之间存在父子关系,你必须打破这种关系。对于Windows,你可以尝试:

Runtime.getRuntime().exec("cmd /c start editor.exe");

对于Linux,该进程似乎仍然是独立运行的,不需要nohup。我试了一下gvimmidoriacroread

import java.io.IOException;
public class Exec {
    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("/usr/bin/acroread");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Finished");
    }
}
2020-03-16