[英]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 应用程序:
Put everything on the module-path, including the JavaFX modules and your module.将所有内容放在模块路径上,包括 JavaFX 模块和您的模块。
Put the JavaFX modules on the module-path and your own code on the class-path.将 JavaFX 模块放在模块路径上,将您自己的代码放在类路径上。
--add-modules
.--add-modules
。 Put everything on the class-path, including the JavaFX modules and your own code.将所有内容放在类路径上,包括 JavaFX 模块和您自己的代码。
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 ". 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。
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 模块和上述模块的路径。
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>
”替换为包含上述代码的路径。
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.