为什么排除META-INF会对Gradle中的“无法找到或加载主方法“有帮助

ryevplcw  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(213)

我试图在Gradle中为我的项目创建一个fat jar。我正在使用这段代码来创建jar。

jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    manifest {
        attributes(
                'Main-Class': 'com.kroger.cxp.app.Main'
        )
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

但是当我尝试运行jar时,它抛出了“无法找到或加载主类”错误。我搜索并将代码更改为

jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    manifest {
        attributes(
                'Main-Class': 'com.kroger.cxp.app.Main'
        )
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }{
        exclude "META-INF/*.SF"
        exclude "META-INF/*.DSA"
        exclude "META-INF/*.RSA"
    }
}

添加这些排除META-INF行后,我可以运行jar,但我仍然不明白这是如何解决问题的?这些META-INF文件是什么,删除它们有什么帮助。

g0czyy6m

g0czyy6m1#

正如JAR file specification所指出的,JAR文件中的META-INF目录包含一个清单文件,可能包含一个索引文件以加速类加载器,并且可能包含一个用于配置的子目录。
你的问题涉及到另一种文件类型--SF和DSA分别是RSA类型的**签名文件。对于每个SF文件,必须有一个同名的DSA或RSA文件。基本上,JAR文件包含的所有文件都列出了它们的验证散列签名。要了解详细信息,请参阅关于签名JAR文件的段落。
因此,如果JAR文件被损坏或篡改,JAR文件将无法运行,因为被修改文件的哈希值与签名文件中记录的哈希值不相等。此外,丢失的文件也会导致错误,因为它们在META-INF中声明,但不在应该在的位置。
所以在你第一次尝试的时候,你创建了一个JAR文件,里面的META-INF签名文件不适合你的JAR文件的实际内容,所以当你试图运行这个JAR文件的时候,你得到了一个错误。
在第二次尝试中,您只是简单地删除了有问题的签名文件,基本上生成了一个未签名的JAR文件,因为签名对于JAR来说不是必须的。
您可以满足于这样的结果,也可以考虑使用jarsigner对JAR进行签名。
附注:在Android操作系统的APK和AAR文件中也会有META-INF,因为这些文件都是有一定结构的JAR文件,但是APK和阿尔斯是强制性的,而JAR是可选的。

相关问题