Gradle - FatJar - 无法找到或加载主文件 class
Gradle - FatJar - Could not find or load main class
我知道这个问题被问了很多并且有很多答案,但我仍然明白,但我不明白为什么...
我正在尝试从具有 gradle 依赖项的项目生成 .jar
。
我有一个 class src/main/java/Launcher.java
,其中有我的 main
方法。
有我的build.gradle
plugins {
id 'java'
id 'application'
}
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = 'Launcher'
repositories {
mavenCentral()
}
dependencies {
compile 'commons-io:commons-io:2.1'
compile 'io.vertx:vertx-core:3.4.0'
compile 'io.vertx:vertx-web:3.4.0'
compile 'com.google.code.gson:gson:1.7.2'
compile "com.auth0:java-jwt:3.1.0"
compile 'org.mongodb:mongo-java-driver:3.4.1'
compile 'com.google.guava:guava:24.1-jre'
compile 'commons-io:commons-io:2.6'
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
我使用 $>gradle assemble
生成我的 jar
然后 $>java -jar path/to/my/.jar
我收到错误 "could not find or load main class Launcher"...
我不明白为什么,当我查看 .jar 时,我有 Launcher class 而在 META-INF 中我有我的清单
很抱歉在 2018 年仍然问这个问题,但我正在失去理智试图找出问题所在。希望有人知道答案!
您正在运行构建 FAT JAR 时遇到一个主要问题:
您的一个源 JAR 已签名,将其合并到一个 fat jar 会破坏签名。
看起来 Java 识别出有未签名的 classes 并忽略除签名的 classes 之外的所有内容。由于所有不属于已签名库的 class 都是未签名的(例如您的 Launcher
class),它们将被忽略,因此无法加载。
在您的情况下,com.auth0:java-jwt:3.1.0
的依赖项 org.bouncycastle:bcprov-jdk15on:1.55
似乎是已签名的 jar 文件。因为当我取消注释此依赖项时,我的示例项目正确执行 Launcher
。
Bouncy castle 是一个需要有效签名的加密提供商,否则根据我的经验,它不会 运行。因此,不可能为您的项目创建一个只包含所有 classes 的 fat jar。
您可以尝试用除 Bouncycastle 之外的所有内容创建一个 fat jar,然后单独运送 Bouncycastle JAR。
或者一个胖罐子,里面包含所有需要的 JAR 文件(JAR inside JAR),并且使用特殊的 class 加载器,能够从这样的 JAR 中加载 classes一个罐子。参见示例:
我在本地重现了你的问题。
只需将 exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
添加到 jar 任务中即可。
这将排除干扰依赖项的签名。
示例:
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
exclude 'META-INF/*.RSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
}
尝试排除 .SF .DSA .RSA 文件,如下例,Nipun
希望这对你有用
task customFatJar(type: Jar) {
baseName = 'XXXXX'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
manifest {
attributes 'Main-Class': 'com.nipun.MyMainClass'
}
}
我知道这个问题被问了很多并且有很多答案,但我仍然明白,但我不明白为什么...
我正在尝试从具有 gradle 依赖项的项目生成 .jar
。
我有一个 class src/main/java/Launcher.java
,其中有我的 main
方法。
有我的build.gradle
plugins {
id 'java'
id 'application'
}
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = 'Launcher'
repositories {
mavenCentral()
}
dependencies {
compile 'commons-io:commons-io:2.1'
compile 'io.vertx:vertx-core:3.4.0'
compile 'io.vertx:vertx-web:3.4.0'
compile 'com.google.code.gson:gson:1.7.2'
compile "com.auth0:java-jwt:3.1.0"
compile 'org.mongodb:mongo-java-driver:3.4.1'
compile 'com.google.guava:guava:24.1-jre'
compile 'commons-io:commons-io:2.6'
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
我使用 $>gradle assemble
生成我的 jar
然后 $>java -jar path/to/my/.jar
我收到错误 "could not find or load main class Launcher"...
我不明白为什么,当我查看 .jar 时,我有 Launcher class 而在 META-INF 中我有我的清单
很抱歉在 2018 年仍然问这个问题,但我正在失去理智试图找出问题所在。希望有人知道答案!
您正在运行构建 FAT JAR 时遇到一个主要问题:
您的一个源 JAR 已签名,将其合并到一个 fat jar 会破坏签名。
看起来 Java 识别出有未签名的 classes 并忽略除签名的 classes 之外的所有内容。由于所有不属于已签名库的 class 都是未签名的(例如您的 Launcher
class),它们将被忽略,因此无法加载。
在您的情况下,com.auth0:java-jwt:3.1.0
的依赖项 org.bouncycastle:bcprov-jdk15on:1.55
似乎是已签名的 jar 文件。因为当我取消注释此依赖项时,我的示例项目正确执行 Launcher
。
Bouncy castle 是一个需要有效签名的加密提供商,否则根据我的经验,它不会 运行。因此,不可能为您的项目创建一个只包含所有 classes 的 fat jar。
您可以尝试用除 Bouncycastle 之外的所有内容创建一个 fat jar,然后单独运送 Bouncycastle JAR。
或者一个胖罐子,里面包含所有需要的 JAR 文件(JAR inside JAR),并且使用特殊的 class 加载器,能够从这样的 JAR 中加载 classes一个罐子。参见示例:
我在本地重现了你的问题。
只需将 exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
添加到 jar 任务中即可。
这将排除干扰依赖项的签名。
示例:
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
exclude 'META-INF/*.RSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
}
尝试排除 .SF .DSA .RSA 文件,如下例,Nipun
希望这对你有用
task customFatJar(type: Jar) {
baseName = 'XXXXX'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
manifest {
attributes 'Main-Class': 'com.nipun.MyMainClass'
}
}