【问题标题】:Gradle Kotlin DSL: could not find or load main classGradle Kotlin DSL:找不到或加载主类
【发布时间】:2021-10-18 18:32:24
【问题描述】:

我有一个包含多个依赖项的 Java 项目,我想用 Gradle 使用 Kotlin DSL 将其打包到一个胖 jar 中。

当我运行./gradlew jar时,构建成功,但是当我尝试运行它时却找不到主类:

$ ./gradlew jar

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

$ java -jar build/libs/myapp-0.0.1-SNAPSHOT.jar
Error: Could not find or load main class mypackage.Hello
Caused by: java.lang.ClassNotFoundException: mypackage.Hello

$ jar xf build/libs/myapp-0.0.1-SNAPSHOT.jar META-INF/MANIFEST.MF
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: mypackage.Hello

$ jar -tf build/libs/myapp-0.0.1-SNAPSHOT.jar | grep mypackage                                                          1
mypackage/
mypackage/Hello.class

这是完整的build.gradle.kts 文件:

group = "myapp"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
    withSourcesJar()
}

plugins {
    java
}

repositories {
    mavenCentral()
    maven {
        url = uri("https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage")
    }
}

dependencies {
    implementation("com.azure:azure-storage-blob:12.12.0")
}

val mainClassName = "mypackage.Hello"
tasks.jar {
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
    manifest.attributes.apply {
        put("Class-Path", configurations.runtimeClasspath.get().asPath)
        put("Main-Class", mainClassName)
    }

    from(configurations.compileClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
}

tasks.test {
    useJUnitPlatform()
}

还有一个指向我的仓库的链接:https://github.com/darkasphalt/myapp

【问题讨论】:

标签: java kotlin gradle build


【解决方案1】:

检查 jar 的内容。问题是,您包含了库的所有内容。这还添加了来自 java 模块系统的文件,例如 module-info.class。这可能会隐藏您的 Main 类。

简单修复

你的主要作品,如果你:

a) 删除导入
implementation("com.azure:azure-storage-blob:12.12.0")

b) 删除类路径配置:
from(configurations.compileClasspath.get().map { if (it.isDirectory) it else zipTree(it) })

比一个简单的java -jar myapp-0.0.1-SNAPSHOT.jar 会打印出:

你好

使用 ShadowJar 设置

要解决正确打包fat jar的问题,您可以使用ShadowJar插件。使用此设置,捆绑的 jar 可以工作:

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

group = "myapp"
version = "0.0.1-SNAPSHOT"

plugins {
    java
    application
    id("com.github.johnrengelman.shadow").version("7.0.0")
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
    withSourcesJar()
}


repositories {
    mavenCentral()
    maven {
        url = uri("https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage")
    }
}

application() {
    mainClass.set("mypackage.Hello")
}

dependencies {
    implementation("com.azure:azure-storage-blob:12.12.0")
}

// Configure Shadow to output with normal jar file name:
tasks.named<ShadowJar>("shadowJar").configure {
    minimize()
}

tasks {
    build {
        dependsOn(shadowJar)
    }
}

tasks.test {
    useJUnitPlatform()
}

【讨论】:

  • 您实际上帮助缩小了我遇到的似乎与 log4j 依赖关系有关的确切问题。一种。删除导入不是一种选择。我以 azure 依赖项为例。我的应用程序有很多其他依赖项,但似乎主要问题是当我尝试导入 log4j 依赖项时。湾。我已经在有关编译 fat jar 的各种 Gradle 帖子中看到了这个类路径配置。我什至在其他已成功编译和运行的项目中使用了相同的确切行。 Gradle 7+ 似乎发生了一些变化。
  • 如果这是您的选择,请查看ShadowJar 构建插件。我用你的构建脚本的工作版本更新了我的答案。
猜你喜欢
  • 2018-09-12
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 2019-10-07
  • 2014-09-15
  • 2021-09-18
  • 1970-01-01
相关资源
最近更新 更多