Problem
这就是你的jlink
task:
'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}"
这意味着您要添加来自以下位置的依赖项:
但是当你运行时,你会得到这个错误:
错误:找不到模块 org.apache.logging.log4j,应用程序需要
该错误意味着module-path
为了jlink
命令不完整,并且无法解析所有必需的依赖项。如上所述,我们仅包含 module.jar 和 JavaFX (jmods) jar,但不包含log4j.jar
.
所以我们需要找到一种方法将该 jar 添加到模块路径中。
有一些可能的解决方案可以在自定义映像中包含第三方依赖项。
解决方案1
我们必须修改jlink
任务,将现有的依赖项包含在我们的运行时配置中。
最直接的解决方案是在本地 .gradle 存储库中查找 gradle 存储 logj4 jar 的位置。
'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}: \
/Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.11.1/268..a10/log4j-api-2.11.1.jar: \
/Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-core/2.11.1/59..e4/log4j-core-2.11.1.jar"
虽然此解决方案有效,但它当然不是最方便的,因为它取决于用户的本地路径。
解决方案2
更好的解决方案是添加一个任务来将运行时依赖项(由 gradle 直接解析)复制到libs
文件夹如:
task libs(type: Copy) {
into 'build/libs/'
from configurations.runtime
}
然后从调用此任务jlink
task:
task jlink(type: Exec) {
dependsOn 'clean'
dependsOn 'jar'
dependsOn 'libs'
...
}
如果你跑./gradlew jlink
并检查libs
文件夹中你应该找到类似这样的内容:
build/libs/hellofx.jar
build/libs/javafx-base-11.0.1.jar
build/libs/javafx-base-11.0.1-$platform.jar
build/libs/javafx-graphics-11.0.1.jar
build/libs/javafx-graphics-11.0.1-$platform.jar
build/libs/javafx-controls-11.0.1.jar
build/libs/javafx-controls-11.0.1-$platform.jar
build/libs/javafx-fxml-11.0.1.jar
build/libs/javafx-fxml-11.0.1-$platform.jar
build/libs/log4j-api-2.11.1.jar
build/libs/log4j-core-2.11.1.jar
where $platform
是你的跑步平台。
请注意,libs
文件夹现在包含all模块路径所需的依赖项,以及 JavaFX-*-$platform jar 所需的依赖项contain本地库,因此,模块路径选项中不再需要 jmod。这就足够了:
'--module-path', "libs"
所以你的命令行将是:
commandLine "${java_home}/bin/jlink", '--module-path', "libs",
'--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'
你可以运行你的jlink
现在任务成功了。
解决方案3
正如 @madhead 评论所建议的,您可以使用另一个插件jlink
任务:所谓的 badass-jlink-插件 https://github.com/beryx/badass-jlink-plugin.
将您的构建修改为:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'org.beryx.jlink' version '2.1.8'
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
}
javafx {
modules = ['javafx.controls', 'javafx.fxml']
}
mainClassName = "${moduleName}/eu.sample.app.Main"
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'helloFX'
}
}
另请注意,该插件可以选择为其他平台创建图像(请参阅目标平台 https://badass-jlink-plugin.beryx.org/releases/latest/#_methods).
编辑关于 log4j
正如评论中提到的,log4j
依赖关系还不能很好地与模块配合使用。有一个开放问题 https://issues.apache.org/jira/projects/LOG4J2/issues/LOG4J2-2438?filter=allopenissues在 Apache 问题跟踪器上:
目前,根据给定的自动模块,您无法在想要使用 jlink 生成运行时映像的项目中使用 log4j-core。
我已将其添加到我的主类中:
LogManager.getLogger(MainApp.class).info("hellofx!");
我添加了log4j2.xml
文件到src/main/resources
.
Running ./gradlew run
, works:
> Task :run
18:24:26.362 [JavaFX Application Thread] INFO eu.sample.app.Main - hellofx!
但是,从解决方案 2 运行 jlink 会创建自定义映像,我可以验证是否包含 xml 文件,但是当从映像运行时,我得到:
build/hellofx/bin/java -m hellofx/eu.sample.app.Main
ERROR StatusLogger Log4j2 could not find a logging implementation. \
Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
And as mentioned, running jlink with the plugin from Solution 3 fails at the createMergedModule
task:
error: package org.apache.logging.log4j.spi is not visible
provides org.apache.logging.log4j.spi.Provider with org.apache.logging.log4j.core.impl.Log4jProvider;
[参见编辑(2),自版本 2.1.9 以来已修复此问题]
选择
此时,可能的替代方案是使用 Slf4j。有一个sample https://github.com/copper-engine/copper-modular-demo从成功使用它的插件文档中列出。
总而言之,这是必需的:
摇篮文件:
dependencies {
compile 'org.slf4j:slf4j-api:1.8.0-beta2'
compile('ch.qos.logback:logback-classic:1.3.0-alpha4') {
exclude module: "activation"
}
}
模块信息:
requires org.slf4j;
requires ch.qos.logback.classic;
requires java.naming;
主要类别:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(MainApp.class);
...
logger.info("hellofx!");
logging.properties
from here https://github.com/copper-engine/copper-modular-demo/blob/master/src/main/resources/logging.properties and logback.xml
from here https://github.com/copper-engine/copper-modular-demo/blob/master/src/main/resources/logback.xml,和你的主课。
两者都在运行./gradlew
run or ./gradlew jlink
, and build/image/bin/HelloFX
工作,并且消息被记录到控制台。
EDIT (2)
After 报告 https://github.com/beryx/badass-jlink-plugin/issues/14badass-jlink-plugin 的问题跟踪器的问题已经解决,并且从版本 2.1.19 开始,创建自定义图像应该可以正常工作。
Since log4j
是多版本jar,需要一件事:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'org.beryx.jlink' version '2.1.9'
}
...
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'helloFX'
}
forceMerge('log4j-api') // <---- this is required for Log4j
}
查看完整的工作示例here https://github.com/beryx-gist/badass-jlink-example-log4j2-javafx.