【问题标题】:getting 'Could not find or load main class' after adding provided spark .jar dependencies to gradle build在将提供的 spark .jar 依赖项添加到 gradle build 后得到“找不到或加载主类”
【发布时间】:2021-05-13 15:39:25
【问题描述】:

我正在尝试使用一些提供的依赖项创建一个可执行的 .jar,并且我有一个 从“gradle init”创建的简单示例,我可以在添加之前执行 .jar 几个提供的依赖项,但是一旦我添加它们就会失败。

我可以重现如下:

mkdir /tmp/foo
cd /tmp/foo
run 'gradle init'

Select type of project to generate:
      2: application

Select implementation language:
      3: Java

Select build script DSL:
  1: Groovy

Select test framework:
  1: JUnit 4

Project name (default: foo):
Source package (default: foo):

然后在 build.gradle 的末尾添加以下内容:

jar {
    manifest {
        attributes "Main-Class": "foo.App"
    }
    zip64 = true
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

在命令行,运行:

gradle clean ; gradle jar ; java -jar  build/libs/foo.jar

你应该看到:

Hello world.

现在将 build.gradle 中的“依赖项”块更改为以下内容:

configurations {
        provided
        compile.extendsFrom(provided)
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'junit:junit:4.13'
    implementation "org.apache.spark:spark-sql_2.11:2.4.4"
    implementation "org.apache.spark:spark-hive_2.11:2.4.4"
}

在命令行,再次运行:

gradle clean ; gradle jar ; java -jar  build/libs/foo.jar

你应该看到一切都很好:

Hello world.

接下来,请更换

    implementation "org.apache.spark:spark-sql_2.11:2.4.4"
    implementation "org.apache.spark:spark-hive_2.11:2.4.4"

    provided "org.apache.spark:spark-sql_2.11:2.4.4"
    provided "org.apache.spark:spark-hive_2.11:2.4.4"

在命令行,再次运行:

gradle clean ; gradle jar ; java -jar  build/libs/foo.jar

这次你会得到:

Error: Could not find or load main class foo.App

所以这显然是由于试图使 Spark 相关的依赖项“提供”,因此 不是 .jar 的一部分。但是,您会注意到 foo.App 类非常简单,并且具有 与火花无关。所以,目前很困惑为什么主类突然变成了 添加这些类型的依赖项时找不到。提前感谢您的帮助!

【问题讨论】:

  • 如果您使用提供,它需要指定的 jars 在您的类路径中,以便您编译代码。这就是您可能会收到此错误的原因。错误似乎具有误导性,但这可能是根本原因。看看这是否有帮助stackoverflow.com/questions/30731084/…

标签: java apache-spark gradle jar executable


【解决方案1】:

您自己可能已经注意到了(这可能也是您想要的):当您使用 provided(或 compile)而不是 implementation 时,构建的 JAR 文件包含来自所有依赖项 JAR 的全部内容dependencies 块。

这里的问题是您的jar 任务配置确实从依赖项 JAR 中获取一切,包括。他们的META-INF/ 目录文件。其中一些依赖项 JAR 似乎已签名,因此在其 META-INF/ 目录中包含数字签名——您的 jar 任务也会复制这些签名。在运行java -jar … 时,这些签名会妨碍并导致找不到类错误(即使类 在 JAR 中)。

一个简单的解决方法是在创建 JAR 文件时排除签名:

jar {
    exclude 'META-INF/*.DSA'
}

学分转到this SO answer

【讨论】:

  • 酷!我得到了使用 shadowJar 插件的东西。但是,一旦我确认它对我有用,我肯定会接受你的答案。非常有趣..谁会想到“排除”。不是我!
【解决方案2】:

这是一个将 Chriki 的解决方案与也适用于我的 shadowJar 方法相结合的答案。任你选!如果这篇文章对您有帮助,请点赞 Chriki 的回答。

plugins {
    // Apply the java plugin to add support for Java
    id 'java'

    // Apply the application plugin to add support for building a CLI application.
    id 'application'

    // This was what I used in my solution
    id 'com.github.johnrengelman.shadow' version '5.2.0'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

configurations {
        provided
        compile.extendsFrom(provided)
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'junit:junit:4.13'
    provided "org.apache.spark:spark-sql_2.11:2.4.4"
    provided "org.apache.spark:spark-hive_2.11:2.4.4"
}


application {
    // Define the main class for the application.
    mainClassName = 'foo.App'
}

test {
    // Use junit platform for unit tests
    useJUnitPlatform()
}

jar {
    // Line below does the trick if you are using 'gradlew jar' 
    // Shout out / big ups to: Chriki
    // Note: My solution (using shadow gradle plugin) 
    // does not require this, but it doesn't hurt
    exclude 'META-INF/*.DSA'            
    manifest {
        attributes "Main-Class": "foo.App"
    }
    zip64 = true
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

// This was the second part of what I used in my solution 
// When building, specify: 'gradlew shadowJar' - the jar you want has -all* in it.
// Run with: java -jar  build/libs/foo-all.jar
shadowJar {
    zip64 = true        // I had to specify this twice.. OK.. not gonna lose sleep.
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多