Выполнение нового приложения JavaFX на отдельной JVM - PullRequest
2 голосов
/ 06 января 2020

Я пытаюсь запустить новый процесс на отдельной JVM с помощью кода, следуя описанному здесь методу: Выполнение Java приложения в отдельном процессе

Код I ' m использует следующее (взято из вопроса выше):

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, я попытался включить команды --module-path и --add-modules в объявление builder, я даже попытался скопировать и вставить всю команду выполнения, и я продолжал получать эту другую ошибку :

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

Как я могу решить эту проблему?

Дайте мне знать, если нужны подробности.

1 Ответ

3 голосов
/ 06 января 2020

С момента появления модулей существует как минимум три различных способа настройки приложения JavaFX:

  1. Поместите все на путь модуля, включая модули JavaFX и ваш модуль. .

    • Это идеальная ситуация, но не всегда возможная / жизнеспособная (например, из-за несовместимых зависимостей).
  2. Поместите модули JavaFX на путь к модулю и ваш собственный код на пути к классам.

    • Эта конфигурация требует использования --add-modules.
  3. Положите все на путь к классу, включая модули JavaFX и ваш собственный код.

    • При такой конфигурации ваш основной класс не может быть подтипом Application. В противном случае вы получите ошибку, о которой вы упоминали в своем вопросе: « Ошибка: отсутствуют компоненты времени выполнения JavaFX, и они необходимы для запуска этого приложения ».
    • Эта конфигурация позволяет легко использовать JAR-файлы fat / uber.

Командная строка, используемая с ProcessBuilder, будет зависеть от конфигурации вашего приложения. Вы также должны принять во внимание любые другие параметры, переданные в командной строке, такие как кодировка по умолчанию или локаль. К сожалению, ваш вопрос не содержит достаточно информации, чтобы сказать, что именно 1039 * идет не так. Ошибка, о которой вы упоминаете, заставляет меня думать, что вы используете третью конфигурацию, но я не уверен.

Тем не менее, я приведу несколько примеров запуска одного и того же приложения из приложения; Вы должны быть в состоянии изменить вещи, чтобы соответствовать вашим потребностям. Примечание. Я использовал 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 <PATH> --module app/com.example.app.Main

Замените "<PATH>" на путь, содержащий как модули 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 <M_PATH> --add-modules javafx.controls --class-path <C_PATH> com.example.app.Main

Замените "<M_PATH>" на путь, содержащий модули JavaFX, и замените "<C_PATH>" на путь, содержащий вышеуказанный код.


Конфигурация # 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 <PATH> com.example.app.Launcher

Заменить "<PATH>" на путь, содержащий JAR-файлы JavaFX и код выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...