Gradle jlink 插件在 createMergedModule 期间失败 "the service implementation does not have a default constructor"
Gradle jlink plugin fails during createMergedModule with "the service implementation does not have a default constructor"
我正在使用 Gradle(4.10.3,但我已经尝试了 5.4.1 之前的大多数版本)以及 JDK 12.0.1 和 org.beryx.jlink
插件( 2.10.4),但每次我尝试创建 jlink 图像时 运行 都会遇到此错误:
-> Task :createMergedModule
Cannot derive uses clause from service loader invocation in:
com/fasterxml/jackson/databind/ObjectMapper.run().
Cannot derive uses clause from service loader invocation in:
com/fasterxml/jackson/databind/ObjectMapper.secureGetServiceLoader().
Cannot derive uses clause from service loader invocation in:
org/apache/commons/compress/utils/ServiceLoaderIterator.().
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:393:
error: the service implementation does not have a default constructor:
XBeansXPath
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with
org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394:
error: the service implementation does not have a default constructor:
XBeansXQuery
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with
org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
2 errors
-> Task :createMergedModule FAILED
当我点击合并 module-info.java
中抛出错误的行时,它指向以下两个:
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
我的 build.gradle
文件如下所示:
plugins {
id 'application'
id 'idea'
id 'java'
id 'org.openjfx.javafxplugin' version '0.0.7'
id 'org.beryx.jlink' version '2.10.4'
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-csv:1.6'
compile 'org.apache.poi:poi-ooxml:4.1.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.9'
testCompile 'org.junit.jupiter:junit-jupiter-api:5.5.0-M1'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.5.0-M1'
}
// ### Application plugin settings
application {
mainClassName = "$moduleName/path.to.myapp"
}
// ### Idea plugin settings
idea {
module {
outputDir = file("out/production/classes")
}
}
// ### Java plugin settings
sourceCompatibility = JavaVersion.VERSION_11
compileJava {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
test {
useJUnitPlatform()
testLogging {
events 'PASSED', 'FAILED', 'SKIPPED'
}
}
// ### JavaFX plugin settings
javafx {
version = "12.0.1"
modules = ['javafx.controls', 'javafx.fxml']
}
// ### jlink plugin settings
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
关于如何解决这个问题的任何想法?
以下可能的解决方案仅基于您的构建文件,不了解您的 module-info 或项目代码,因此它可能无法工作。
它也是基于 jlink 插件存储库中的 issue。
首先,让我解释一下这个插件是如何工作的:由于 (JDK) jlink
工具不允许 non-modular 依赖项,插件将尝试收集所有依赖项并即时创建一个模块,可以将其添加到 module-path。此模块名为 $yourModuleName.mergedModule
.
现在我将您的依赖项添加到一个简单的 JavaFX 项目中。当我 运行 ./gradlew jlink
时,我得到了与您发布的相同的错误。如果检查错误:
myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394: error
这表明创建的模块名为 myapp.merged.module
,并且它有一个 module-info
描述符。如果你打开它,你会看到所有的 exports
(该模块默认会导出每个依赖包)、requires
和 provides
:
open module myapp.merged.module {
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
requires java.xml.crypto;
requires java.logging;
requires java.sql;
requires java.xml;
requires java.desktop;
requires java.security.jgss;
requires jdk.javadoc;
uses java.nio.file.spi.FileSystemProvider;
provides com.fasterxml.jackson.core.JsonFactory with com.fasterxml.jackson.core.JsonFactory;
provides com.fasterxml.jackson.core.ObjectCodec with com.fasterxml.jackson.databind.ObjectMapper;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
}
那么现在的问题是:你是否应该在你自己的模块中增加一些需求?答案解释here: that will increase unnecessary your project's size. A better way is to use the mergedModule
脚本块:
The mergedModule block allows you to configure the module descriptor of the merged module
并且:
the module descriptor is created using the algorithm implemented by the suggestMergedModuleInfo
task.
如果你 运行 ./gradlew suggestMergedModuleInfo
你基本上会得到与上面相同的合并模块描述符的内容。
一个可能的解决方案是开始只向合并的模块描述符添加一些要求,然后重试。
我开始于:
jlink {
mergedModule {
requires "java.xml"
}
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
我可以 运行 ./gradlew jlink
成功。
如果您现在检查合并的模块描述符,它将看起来像:
open module myapp.merged.module {
requires java.xml;
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
}
仅包含显式 requires
,所有导出,但不包含 provides
,因此错误将消失。
因为我没有你的代码,所以我不能说这是否适合你,但它对我有相同的依赖关系。
我正在使用 Gradle(4.10.3,但我已经尝试了 5.4.1 之前的大多数版本)以及 JDK 12.0.1 和 org.beryx.jlink
插件( 2.10.4),但每次我尝试创建 jlink 图像时 运行 都会遇到此错误:
-> Task :createMergedModule
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper.run().
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper.secureGetServiceLoader().
Cannot derive uses clause from service loader invocation in: org/apache/commons/compress/utils/ServiceLoaderIterator.().
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:393: error: the service implementation does not have a default constructor: XBeansXPath provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394: error: the service implementation does not have a default constructor: XBeansXQuery provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery; 2 errors
-> Task :createMergedModule FAILED
当我点击合并 module-info.java
中抛出错误的行时,它指向以下两个:
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
我的 build.gradle
文件如下所示:
plugins {
id 'application'
id 'idea'
id 'java'
id 'org.openjfx.javafxplugin' version '0.0.7'
id 'org.beryx.jlink' version '2.10.4'
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-csv:1.6'
compile 'org.apache.poi:poi-ooxml:4.1.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.9'
testCompile 'org.junit.jupiter:junit-jupiter-api:5.5.0-M1'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.5.0-M1'
}
// ### Application plugin settings
application {
mainClassName = "$moduleName/path.to.myapp"
}
// ### Idea plugin settings
idea {
module {
outputDir = file("out/production/classes")
}
}
// ### Java plugin settings
sourceCompatibility = JavaVersion.VERSION_11
compileJava {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
test {
useJUnitPlatform()
testLogging {
events 'PASSED', 'FAILED', 'SKIPPED'
}
}
// ### JavaFX plugin settings
javafx {
version = "12.0.1"
modules = ['javafx.controls', 'javafx.fxml']
}
// ### jlink plugin settings
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
关于如何解决这个问题的任何想法?
以下可能的解决方案仅基于您的构建文件,不了解您的 module-info 或项目代码,因此它可能无法工作。
它也是基于 jlink 插件存储库中的 issue。
首先,让我解释一下这个插件是如何工作的:由于 (JDK) jlink
工具不允许 non-modular 依赖项,插件将尝试收集所有依赖项并即时创建一个模块,可以将其添加到 module-path。此模块名为 $yourModuleName.mergedModule
.
现在我将您的依赖项添加到一个简单的 JavaFX 项目中。当我 运行 ./gradlew jlink
时,我得到了与您发布的相同的错误。如果检查错误:
myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394: error
这表明创建的模块名为 myapp.merged.module
,并且它有一个 module-info
描述符。如果你打开它,你会看到所有的 exports
(该模块默认会导出每个依赖包)、requires
和 provides
:
open module myapp.merged.module {
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
requires java.xml.crypto;
requires java.logging;
requires java.sql;
requires java.xml;
requires java.desktop;
requires java.security.jgss;
requires jdk.javadoc;
uses java.nio.file.spi.FileSystemProvider;
provides com.fasterxml.jackson.core.JsonFactory with com.fasterxml.jackson.core.JsonFactory;
provides com.fasterxml.jackson.core.ObjectCodec with com.fasterxml.jackson.databind.ObjectMapper;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
}
那么现在的问题是:你是否应该在你自己的模块中增加一些需求?答案解释here: that will increase unnecessary your project's size. A better way is to use the mergedModule
脚本块:
The mergedModule block allows you to configure the module descriptor of the merged module
并且:
the module descriptor is created using the algorithm implemented by the
suggestMergedModuleInfo
task.
如果你 运行 ./gradlew suggestMergedModuleInfo
你基本上会得到与上面相同的合并模块描述符的内容。
一个可能的解决方案是开始只向合并的模块描述符添加一些要求,然后重试。
我开始于:
jlink {
mergedModule {
requires "java.xml"
}
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
我可以 运行 ./gradlew jlink
成功。
如果您现在检查合并的模块描述符,它将看起来像:
open module myapp.merged.module {
requires java.xml;
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
}
仅包含显式 requires
,所有导出,但不包含 provides
,因此错误将消失。
因为我没有你的代码,所以我不能说这是否适合你,但它对我有相同的依赖关系。