热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:在单独的JVM上执行新的JavaFX应用程序

篇首语:本文由编程笔记#小编为大家整理,主要介绍了在单独的JVM上执行新的JavaFX应用程序相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了在单独的JVM上执行新的JavaFX应用程序相关的知识,希望对你有一定的参考价值。



我正在尝试按照此处所示的方法通过代码在单独的JVM上启动新进程:Executing a Java application in a separate process

我正在使用的代码如下(摘自上述问题):

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();

......其中klass是我要启动的类。这对于正常的Java进程是可行的,但问题是我正在尝试启动JavaFX应用程序,并且上面的代码生成以下错误:

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

因此,要添加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.

我该如何解决?

让我知道是否需要详细信息。

答案
自模块问世以来,至少可以通过三种不同的方式配置JavaFX应用程序:
  1. 将所有内容放在模块路径上,包括JavaFX模块和您的模块。
      这是理想的情况,但并非总是可行/可行的(例如,由于依赖性不兼容)。
  2. 将JavaFX模块放在模块路径上,并将您自己的代码放在类路径上。
      此配置需要使用--add-modules
  3. 将所有内容放在类路径中,包括JavaFX模块和您自己的代码。
      使用此配置,您的主类
    • 无法是Application的子类型。否则,您将得到在问题中提到的错误:“ 错误:缺少JavaFX运行时组件,并且是运行此应用程序所必需的]”。
    • 此配置可轻松使用所谓的胖/超级JAR。
  • ProcessBuilder使用的命令行将取决于您的应用程序使用哪种配置。您还必须考虑通过命令行传递的任何其他选项,例如默认编码或区域设置。不幸的是,您的问题没有提供足够的信息来说明

    exactly出了什么问题。您提到的错误使我认为您正在使用第三种配置,但是我不确定。

    也就是说,我将给出一些从应用程序内部启动相同应用程序的示例;您应该能够根据自己的需要进行修改。注意测试以下代码时,我使用了Java / JavaFX 13.0.1。
    配置#1

    将所有内容放在模块路径上。

    module-info.java:

    module app
    requires javafx.controls;
    exports com.example.app to
    javafx.graphics;

    Main.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();

    命令行:

    java --module-path --module app/com.example.app.Main

    用包含JavaFX模块和上述模块的路径替换“ ”。


    配置#2

    将JavaFX模块放在模块路径上,将代码放在类路径上。

    Main.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();

    命令行:

    java --module-path --add-modules javafx.controls --class-path com.example.app.Main

    用包含JavaFX模块的路径替换“ ”,并用包含上述代码的路径替换“ ”。


    配置#3

    将所有内容放在类路径上。请注意,主类(现在为Launcher)不是Application的子类。

    Launcher.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:

    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();

    命令行:

    java --class-path com.example.app.Launcher

    用包含JavaFX JAR和上面代码的路径替换“ ”。


  • 推荐阅读
    • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
    • 优化ListView性能
      本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
    • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
    • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
    • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
    • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
    • Java 类成员初始化顺序与数组创建
      本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
    • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
    • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
    • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
    • Android 渐变圆环加载控件实现
      本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
    • 将Web服务部署到Tomcat
      本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
    • MQTT技术周报:硬件连接与协议解析
      本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
    • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
    • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
    author-avatar
    小池子的思密达
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有