我想启动一个 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());
}
}
使用 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);