简体   繁体   English

在单独的 JVM 上执行新的 JavaFX 应用程序

[英]Executing a new JavaFX application on a separate JVM

I'm trying to launch a new process on a separate JVM via code following the method illustrated here: Executing a Java application in a separate process我正在尝试按照此处说明的方法通过代码在单独的 JVM 上启动一个新进程: 在单独的进程中执行 Java 应用程序

The code I'm using is the following (taken from the question above):我使用的代码如下(取自上述问题):

public static int exec(Class klass) throws IOException, InterruptedException {
        String javaHome = System.getProperty("java.home");
        String javaBin = javaHome +
                File.separator + "bin" +
                File.separator + "java";
        String classpath = System.getProperty("java.class.path");
        String className = klass.getName();

        ProcessBuilder builder = new ProcessBuilder(javaBin,"-cp",classpath,className);
        Process process = builder.inheritIO().start();
        process.waitFor();
        return process.exitValue();
    }

...in which klass is the class I want to launch. ...其中klass是我想要启动的类。 This would work for a normal Java process, but the problem is that I'm trying to launch a JavaFX application, and the code above generates the following error:这适用于普通的 Java 进程,但问题是我正在尝试启动 JavaFX 应用程序,并且上面的代码生成以下错误:

Error: JavaFX runtime components are missing, and are required to run this application

So, to add the JavaFX modules, I tried including the --module-path and --add-modules commands in the declaration of builder , I even attempted copying and pasting the entire execution command, and I kept getting this other error:因此,为了添加 JavaFX 模块,我尝试在builder的声明中包含 --module-path 和 --add-modules 命令,我什至尝试复制和粘贴整个执行命令,但我不断收到另一个错误:

Unrecognized option: (command string with modules)
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

How could I solve this?我怎么能解决这个问题?

Let me know if details are needed.如果需要详细信息,请告诉我。

Since the advent of modules, there are at least three different ways a JavaFX application can be configured:自从模块出现以来,至少可以通过三种不同的方式配置 JavaFX 应用程序:

  1. Put everything on the module-path, including the JavaFX modules and your module.将所有内容放在模块路径上,包括 JavaFX 模块和您的模块。

    • This is the ideal situation but not always possible/viable (eg because of incompatible dependencies).这是理想的情况,但并不总是可能/可行(例如,由于不兼容的依赖关系)。
  2. Put the JavaFX modules on the module-path and your own code on the class-path.将 JavaFX 模块放在模块路径上,将您自己的代码放在类路径上。

    • This configuration requires the use of --add-modules .此配置需要使用--add-modules
  3. Put everything on the class-path, including the JavaFX modules and your own code.将所有内容放在类路径上,包括 JavaFX 模块和您自己的代码。

    • With this configuration your main class cannot be a subtype of Application .使用此配置,您的主类不能Application的子类型。 Otherwise you get the error you mentioned in your question: " Error: JavaFX runtime components are missing, and are required to run this application ".否则,您会收到问题中提到的错误:“错误:缺少 JavaFX 运行时组件,需要运行此应用程序”。
    • This configuration allows for easy use of so-called fat/uber JARs.这种配置允许轻松使用所谓的胖/超级 JAR。
    • Warning: This approach is explicitly unsupported .警告:此方法明确不受支持

The command line used with ProcessBuilder will depend on which configuration your application uses.ProcessBuilder使用的命令行将取决于您的应用程序使用的配置。 You also have to take into account any other options passed the command line, such as the default encoding or locale.您还必须考虑通过命令行传递的任何其他选项,例如默认编码或区域设置。 Unfortunately, your question doesn't provide enough information to tell what exactly is going wrong.不幸的是,你的问题并没有提供足够的信息来告诉究竟是怎么了。 The error you mention makes me think you're using the third configuration, but I can't be sure.您提到的错误让我认为您使用的是第三种配置,但我不能确定。

That said, I'll give some examples of launching the same application from within the application;也就是说,我将给出一些从应用程序内部启动相同应用程序的示例; you should be able to modify things to fit your needs.您应该能够修改内容以满足您的需求。 Note I used Java/JavaFX 13.0.1 when testing the below code.注意我在测试以下代码时使用了 Java/JavaFX 13.0.1。


Configuration #1配置#1

Put everything on the module-path.将所有内容放在模块路径上。

module-info.java:模块信息.java:

module app {
  requires javafx.controls;

  exports com.example.app to
      javafx.graphics;
}

Main.java:主.java:

package com.example.app;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import static java.lang.System.getProperty;

public class Main extends Application {

  private static void launchProcess() {
    try {
      new ProcessBuilder(
              Path.of(getProperty("java.home"), "bin", "java").toString(),
              "--module-path",
              getProperty("jdk.module.path"),
              "--module",
              getProperty("jdk.module.main") + "/" + getProperty("jdk.module.main.class"))
          .inheritIO()
          .start();
    } catch (IOException ex) {
      throw new UncheckedIOException(ex);
    }
  }

  @Override
  public void start(Stage primaryStage) {
    Button launchBtn = new Button("Launch process");
    launchBtn.setOnAction(
        event -> {
          event.consume();
          launchProcess();
        });
    primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
    primaryStage.setTitle("Multi-Process Example");
    primaryStage.show();
  }
}

Command line:命令行:

java --module-path <PATH> --module app/com.example.app.Main

Replace " <PATH> " with a path containing both the JavaFX modules and the above module.将“ <PATH> ”替换为包含 JavaFX 模块和上述模块的路径。


Configuration #2配置#2

Put JavaFX modules on the module-path and your code on the class-path.将 JavaFX 模块放在模块路径上,将您的代码放在类路径上。

Main.java:主.java:

package com.example.app;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import static java.lang.System.getProperty;

public class Main extends Application {

  private static void launchProcess() {
    try {
      new ProcessBuilder(
              Path.of(getProperty("java.home"), "bin", "java").toString(),
              "--module-path",
              getProperty("jdk.module.path"),
              "--add-modules",
              "javafx.controls",
              "--class-path",
              getProperty("java.class.path"),
              Main.class.getName())
          .inheritIO()
          .start();
    } catch (IOException ex) {
      throw new UncheckedIOException(ex);
    }
  }

  @Override
  public void start(Stage primaryStage) {
    Button launchBtn = new Button("Launch process");
    launchBtn.setOnAction(
        event -> {
          event.consume();
          launchProcess();
        });
    primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
    primaryStage.setTitle("Multi-Process Example");
    primaryStage.show();
  }
}

Command line:命令行:

java --module-path <M_PATH> --add-modules javafx.controls --class-path <C_PATH> com.example.app.Main

Replace " <M_PATH> " with a path containing the JavaFX modules and replace " <C_PATH> " with a path containing the above code.将“ <M_PATH> ”替换为包含JavaFX 模块的路径,将“ <C_PATH> ”替换为包含上述代码的路径。


Configuration #3配置#3

Put everything on the class-path.将所有内容放在类路径上。 Note the main class (now Launcher ) is not a subclass of Application .注意主类(现在Launcher )不是Application的子类。

Launcher.java:启动器.java:

package com.example.app;

import javafx.application.Application;

public class Launcher {

  public static void main(String[] args) {
    Application.launch(Main.class, args);
  }
}

Main.java:主.java:

package com.example.app;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import static java.lang.System.getProperty;

public class Main extends Application {

  private static void launchProcess() {
    try {
      new ProcessBuilder(
              Path.of(getProperty("java.home"), "bin", "java").toString(),
              "--class-path",
              getProperty("java.class.path"),
              Launcher.class.getName())
          .inheritIO()
          .start();
    } catch (IOException ex) {
      throw new UncheckedIOException(ex);
    }
  }

  @Override
  public void start(Stage primaryStage) {
    Button launchBtn = new Button("Launch process");
    launchBtn.setOnAction(
        event -> {
          event.consume();
          launchProcess();
        });
    primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
    primaryStage.setTitle("Multi-Process Example");
    primaryStage.show();
  }
}

Command line:命令行:

java --class-path <PATH> com.example.app.Launcher

Replace " <PATH> " with a path containing the JavaFX JARs and the above code.将“ <PATH> ”替换为包含 JavaFX JAR 和上述代码的路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Netbeans无法正确执行JavaFX应用程序 - Netbeans not executing JavaFX application properly 从单独的JVM访问应用程序上下文和bean? - Accessing application context and bean from separate JVM? 在单独的进程中执行 Java 应用程序 - Executing a Java application in a separate process 使用正在运行的JavaFX应用程序,使用自己独立的控制器类打开一个新窗口 - With a running JavaFX application, open a new window with its own, separate controller class 如何将AnimationTimer与JavaFX应用程序线程分开? - How to separate AnimationTimer from the JavaFX application thread? 如何将JVM参数传递给使用Inno Setup创建的本机JavaFX 2应用程序 - How to pass JVM arguments to a native JavaFX 2 application created with Inno Setup Java:在新的JVM实例中执行对象并获取结果 - java: executing a Object in new JVM instance and getting the results 如何启动新的JavaFX(应用程序)线程? - How to start new JavaFX (Application) thread? 带有非英语参数的捆绑JavaFX应用程序抛出“无法启动JVM” - Bundled JavaFX application runs with non-English arguments throws “Could not start JVM” 如何将动态JVM命令行标志传递给自包含的JavaFX应用程序? - How can dynamic JVM command line flags be passed to a self-contained JavaFX application?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM