Пакет немодульного приложения JavaFX - PullRequest
0 голосов
/ 06 января 2019

У меня есть приложение Java 8, которое использует JavaFX и где расширяется основной класс javafx.application.Application . В настоящее время я поставляю его в виде полной фляги, и он отлично работает на Oracle Java 8.

Теперь я хочу, чтобы он мог работать на OpenJDK 11. Чтобы добавить JavaFX, я уже добавил артефакты из org.openjfx в путь к классам и включаю их в толстый флягу. Если я запускаю банку из командной строки, я получаю

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

Я нашел два возможных пути решения этой проблемы:

  1. Грязный: напиши специальный пусковой механизм, который не расширяет Application, и обойди проверку модуля. Смотри http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-June/021977.html
  2. Чистый: добавьте --module-path и --add-modules в мою командную строку. Проблема этого решения в том, что я хочу, чтобы мои конечные пользователи могли просто запустить приложение, дважды щелкнув по нему.

Хотя я мог бы пойти с 1. в качестве обходного пути, мне интересно, каков в настоящее время (OpenJDK 11) предполагаемый способ создания / доставки исполняемых толстых фляг немодульных приложений JavaFX. Кто-нибудь может помочь?

1 Ответ

0 голосов
/ 06 января 2019

Это несколько вариантов упаковки / распространения (немодульного) конечного приложения JavaFX 11. Большинство из них описаны в официальных документах OpenJFX .

Я буду использовать этот образец в качестве ссылки. Я также буду использовать Gradle. Подобное можно сделать с помощью Maven (разные плагины) и даже без инструментов сборки (но это не рекомендуется ...). Инструменты для сборки сегодня необходимы.

Fat Jar

Это все еще допустимый вариант, но не предпочтительный, поскольку он ломает модульную конструкцию и объединяет все вместе, и он не является кроссплатформенным, если вы не позаботитесь об этом.

Для данного примера у вас есть файл build.gradle, подобный этому:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

repositories {
    mavenCentral()
}

dependencies {
}

javafx {
    modules = [ 'javafx.controls' ]
}

mainClassName = 'hellofx.HelloFX'

jar {
    manifest {
        attributes 'Main-Class': 'hellofx.Launcher'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Обратите внимание на использование класса Launcher. Как упоминается в OP или объясняется здесь , для создания толстой банки требуется класс средства запуска, не выходящий за пределы Application.

Запуск ./gradlew jar создает толстый jar (~ 8 МБ), который включает в себя классы JavaFX и собственные библиотеки вашей текущей платформы.

Вы можете запустить java -jar build/libs/hellofx.jar как обычно, но только на той же платформе.

Как объяснено в документации OpenJFX или здесь , вы все равно можете создать кроссплатформенную флягу.

В этом случае мы можем включить три графических фляги, поскольку они имеют зависящий от платформы код и библиотеки. Модули base, controls и fxml не зависят от платформы.

dependencies {
    compile "org.openjfx:javafx-graphics:11.0.1:win"
    compile "org.openjfx:javafx-graphics:11.0.1:linux"
    compile "org.openjfx:javafx-graphics:11.0.1:mac"
}

./gradlew jar теперь создаст толстую банку (19 МБ), которую можно распространить на эти три платформы.

(Примечание. На носителях и в Интернете также есть зависимый от платформы код / ​​собственные библиотеки).

Так что это работает так же, как и в Java 8. Но, как я уже говорил, оно нарушает работу модулей и не соответствует тому, как библиотеки и приложения распространяются в настоящее время.

И не забывайте, что пользователям этих jar-ов все равно придется устанавливать JRE.

JLINK

Так как насчет распространения пользовательского изображения в вашем проекте, который уже включает в себя собственный JRE и модуль запуска?

Вы скажете, что если у вас немодулярный проект, это не сработает. Правда. Но давайте рассмотрим два варианта, прежде чем говорить о jpackage.

среда-плагин

badass-runtime-plugin - это плагин Gradle, который создает образы времени выполнения из немодульных проектов.

С помощью этого build.gradle:

plugins {
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'org.beryx.runtime' version '1.0.0'
    id "com.github.johnrengelman.shadow" version "4.0.3"
}

repositories {
    mavenCentral()
}

dependencies {
}

javafx {
    modules = [ 'javafx.controls' ]
}

mainClassName = 'hellofx.Launcher'

runtime {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
}

Когда вы запустите ./gradlew runtime, он создаст среду выполнения со своим средством запуска, чтобы вы могли запустить:

cd build/image/hellofx/bin
./hellofx

Обратите внимание, что он опирается на плагин shadow и также требует класс Launcher.

Если вы запустите ./gradlew runtimeZip, вы можете получить zip для этого пользовательского образа размером около 32,5 МБ.

Опять же, вы можете распространять этот zip-файл любому пользователю с той же платформой, но теперь нет необходимости устанавливать JRE.

См. targetPlatform для построения изображений для других платформ.

Going Modular

Мы продолжаем думать, что у нас немодулярный проект, и это нельзя изменить ... но что, если мы его изменим?

Модульный переход не так уж и велик: вы добавляете дескриптор module-info.java и включаете в него необходимые модули, даже если это немодулярные файлы jar (основанные на автоматических именах) .

На основе того же примера я добавлю дескриптор:

module hellofx {
    requires javafx.controls;

    exports hellofx;
}

И теперь я могу использовать jlink в командной строке или использовать плагин для него. badass-gradle-plugin - плагин gradle того же автора, что и упомянутый выше, который позволяет создавать пользовательскую среду выполнения.

С этим файлом сборки:

plugins {
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'org.beryx.jlink' version '2.3.0'
}

repositories {
    mavenCentral()
}

dependencies {
}

javafx {
    modules = [ 'javafx.controls' ]
}

mainClassName = 'hellofx/hellofx.HelloFX'

Вы можете запустить сейчас:

./gradlew jlink
cd build/image/bin/hellofx
./hellofx

или ./gradlew jlinkZip для сжатой версии (31 МБ), которую можно распространять и запускать на компьютерах той же платформы, даже если JRE не установлено.

Как видите, не нужен плагин shadow или класс Launcher. Вы также можете использовать другие платформы или включать немодулярные зависимости, как в этом вопросе .

JPackage

Наконец, появился новый инструмент для создания исполняемых установщиков, который вы можете использовать для распространения своего приложения.

Пока еще нет версии GA (вероятно, нам придется ждать Java 13), но есть два варианта ее использования с Java 11 или 12:

В Java / JavaFX 11 есть обратный порт от начальной работы на JPackager на Java 12, который вы можете найти здесь . Есть хорошая статья об использовании здесь , и проект gradle для его использования здесь .

В Java / JavaFX 12 уже есть build 0 version инструмента jpackage, который будет доступен в Java 13.

Это очень предварительное использование инструмента:

plugins {
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

repositories {
    mavenCentral()
}

dependencies {
}

javafx {
    version = "12-ea+5"
    modules = [ 'javafx.controls' ]
}

mainClassName = 'hellofx/hellofx.HelloFX'

def java_home = '/Users/<user>/Downloads/jdk-12.jdk/Contents/Home'
def installer = 'build/installer'
def appName = 'HelloFXApp'

task copyDependencies(type: Copy) {
    dependsOn 'build'
    from configurations.runtime
    into "${buildDir}/libs"
}

task jpackage(type: Exec) {
    dependsOn 'clean'
    dependsOn 'copyDependencies'

    commandLine "${java_home}/bin/jpackage", 'create-installer', "dmg",
            '--output', "${installer}", "--name", "${appName}",
            '--verbose', '--echo-mode', '--module-path', 'build/libs',
            '--add-modules', "${moduleName}", '--input', 'builds/libraries',
            '--class', "${mainClassName}", '--module', "${mainClassName}"
}

Сейчас работает ./gradlew jpackage генерирует dmg (65 МБ), который я могу распространять для установки:

installer

* +1136 * Заключение

Хотя вы можете придерживаться классических толстых банок, при переходе на Java 11 и более поздние версии все должно быть модульным. Новые (скоро появившиеся) доступные инструменты и плагины, включая поддержку IDE, помогают в этом переходе.

Я знаю, что я представил здесь простейший вариант использования, и что при рассмотрении более сложных реальных случаев будет несколько проблем ... Но мы должны лучше работать над решением этих проблем, а не использовать устаревшие решения.

...