Это несколько вариантов упаковки / распространения (немодульного) конечного приложения 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 МБ), который я могу распространять для установки:
* +1136 * Заключение
Хотя вы можете придерживаться классических толстых банок, при переходе на Java 11 и более поздние версии все должно быть модульным. Новые (скоро появившиеся) доступные инструменты и плагины, включая поддержку IDE, помогают в этом переходе.
Я знаю, что я представил здесь простейший вариант использования, и что при рассмотрении более сложных реальных случаев будет несколько проблем ... Но мы должны лучше работать над решением этих проблем, а не использовать устаревшие решения.