如何在独立进程中启动JavaFX应用程序

时间:2018-03-12 10:22:25

标签: java javafx jvm multiprocessing

我想启动一个JavaFX应用程序,如果它还没有运行的话。

JavaFX应用程序打包在JAR容器中,该容器位于调用应用程序的类路径中。调用应用程序应该执行JavaFX应用程序。

如果调用应用程序被终止,则JavaFX应用程序不应终止。 (因此它需要在一个单独的过程中)

我尝试了以下方法,但即使uiProcess.isAlive()返回true,JavaFX应用程序也永远不可见。

// caller main thread
String[] startOptions = new String[]{"java", "-jar", "javafx-ui.jar"}; 
Process uiProcess = new ProcessBuilder(startOptions).start();

+++++++++++++++++++++++++++++++++++++++

更新:

我创建了一个辅助类,它接受JAR名称并尝试执行它。不幸的是,这不起作用。但是,如果我复制记录的CLI命令并在终端中执行命令,则应用程序将按预期启动。如果我打印System.getProperty("java.class.path")属性,我看到我的javafx-ui.jar在类路径上。

用法:

    ProcessExecutor processExecutor = new ProcessExecutor();
    processExecutor.executeJarByName("javafx-ui.jar");

执行人:

public class ProcessExecutor {
    private List<Process> processes;

    private static Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);

    /**
     * Default constructor
     */
    public ProcessExecutor() {
        processes = new ArrayList<>();
    }

    /**
     * Executes jar in a standalone process
     *
     * @param jarName
     */
    public Process executeJarByName(String jarName) throws IOException {
        String[] command = new String[]{"java", "-jar", jarName};
        ProcessBuilder builder = createProcessBuilder(command);
        Process process = builder.start();
        processes.add(process);

        if (process.isAlive()) {

            Optional<ProcessHandle> processHandle = ProcessHandle.of(process.pid());
            if (processHandle.isPresent()) {
                ProcessHandle.Info processInfo = processHandle.get().info();
                logger.info("COMMAND: {}", processInfo.command().orElse(""));
                logger.info("CLI: {}", processInfo.commandLine().orElse(""));
                logger.info("USER: {}", processInfo.user().orElse(""));
                logger.info("START TIME: {}", processInfo.startInstant().orElse(null));
                logger.info("TOTAL CPU: {}", processInfo.totalCpuDuration().orElse(null));
            }
        }
        return process;
    }

    private ProcessBuilder createProcessBuilder(String[] command) {
        return new ProcessBuilder(command);
    }

    /**
     * Kills all executed processes
     */
    public void killAll() {
        processes.forEach(p -> p.destroy());
    }
}

1 个答案:

答案 0 :(得分:0)

如果我使用Java ProcessBuilder执行以下命令,我就可以了。 mainClassName必须是类的完全限定类名,包含main()方法。 (包括包名)

    String separator = System.getProperty("file.separator");
    String classpath = System.getProperty("java.class.path");
    String javaHome = System.getProperty("java.home");
    String java = javaHome + separator + "bin" + separator + "java";

    String[] command = {java, "-cp", classpath, mainClassName};
    ProcessBuilder builder = createProcessBuilder(command);