【问题标题】:Signing java 11 jar with jarsigner duplicate entry module-info.class使用 jarsigner 重复条目 module-info.class 对 java 11 jar 进行签名
【发布时间】:2019-05-22 22:46:50
【问题描述】:

您好,我是 java 模块的新手,所以这可能是一个愚蠢的问题。

我尝试使用密钥库对我的 jar 文件进行签名,但出现以下错误。

user@Ubuntu:libs(master)$ jarsigner -keystore keyStoreFileName Test.jar alias
Enter Passphrase for keystore: 
jarsigner: unable to sign jar: java.util.zip.ZipException: duplicate entry: module-info.class

我找不到任何有关如何避免这种情况的文档。

所以我做了 jar -tf 来检查 jar 的内容,是的,它确实有多个 module-info.class 文件

有没有组合它们的选项?以及如何?

我的 module-info.java 包含以下内容。

module module_name {
    requires java.desktop;
    requires java.prefs;
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.web;
    requires org.jsoup;
    opens com.test.apps to javafx.fxml;
    exports com.test.apps;
}

我正在用这样的 gradle 创建 jar

jar {
    manifest {
        attributes 'Main-Class': 'com.test.apps.Main'
        attributes 'Application-Name': 'Test'
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }

}

我知道我不应该发布屏幕截图,但这是使用存档管理器打开的 jar

有 7 个 module-info.class 文件,第一个在 2018 年 12 月 23 日(今天)生成,其余都是从 18 年 11 月 5 日开始的,我记得那天升级到 java 11,

所以这些是从我的依赖项中添加的,我怎样才能将它们集成到一个类中?还是有其他选择来签署一个罐子?

再次,这是来自菜鸟。

[编辑] 如果你正在寻找完整的源代码,它在 GitHub -> https://github.com/CodingOtaku/Animu-Downloaderu

【问题讨论】:

  • 为什么你的 jar 文件中有多个 module-info.class
  • @nullpointer 我不知道,它是这样生成的。也许它正在从依赖项中添加所有 modules-info.class 我将添加一个屏幕截图

标签: java jarsigner java-11 jar-signing


【解决方案1】:

根据您发布的 build.gradle 内容,当您运行时:

./gradlew jar

您正在创建一个胖/影子 jar,它将所有依赖项捆绑在一起,包括一个大 jar 中的模块化依赖项。此过程将每个 jar(类和资源)中的所有文件提取到 libs 文件夹中,最后将其压缩到项目的影子 jar 中。

模块化依赖项(至少是 JavaFX jars)在其 jar 文件中包含一个 module-info.class 文件。所以这些将被添加到 libs 文件夹中。

作为jar 任务的结果,根据您的平台,您最终可能只得到这些文件中的一个(如果将同名文件粘贴到一个文件中,则添加第一个或最后一个文件) , 或所有文件(如果保留所有同名文件,这似乎是你的情况)。

无论哪种方式,由于您正在创建一个胖罐子,因此您将其运行为:

java -jar my-fat-jar.jar

为此,您根本不需要模块。

解决方案

所以一个简单的解决方案是从你的 fat jar 中排除模块信息文件:

jar {
    manifest {
        attributes 'Main-Class': 'your.main.class'
    }
    from {
        exclude '**/module-info.class'
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

跨平台的jar

请注意,releasing 的 jar 不是跨平台的,因为它只包含 Linux 的本机库。

创建跨平台 jar 的一个选项可以在 here 中找到,非模块化应用程序 -> Gradle -> 跨平台 jar 部分。

jlink

您也可以考虑使用jlink 进行分发,因为您的应用已经是modular

在这种情况下,您将为给定平台生成自定义图像。您可以考虑为每个平台创建一个。

请参阅此 doc,使用 Gradle 进行模块化部分,并使用 jlink 任务,或尝试改用 badass-jlink-plugin

jpackage

jpackage 工具中有一个preview 用于 Java 12。有了它,您可以为每个平台创建一个安装程序。

【讨论】:

  • 谢谢!这正是我想要的!
猜你喜欢
  • 1970-01-01
  • 2019-04-03
  • 2019-03-13
  • 1970-01-01
  • 2021-08-18
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 2019-07-16
相关资源
最近更新 更多