簡體   English   中英

在將提供的 spark.jar 依賴項添加到 gradle 構建后得到“找不到或加載主類”

[英]getting 'Could not find or load main class' after adding provided spark .jar dependencies to gradle build

我正在嘗試使用一些提供的依賴項創建一個可執行文件.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 的一部分。 但是,您會注意到 class foo.App 非常簡單,與 Spark 無關。 所以,目前很困惑為什么在添加這些類型的依賴項時,主 class 突然變得無法找到。 在此先感謝您的幫助 !

您可能自己已經注意到了(這可能也是您想要的):當您使用provided (或compile )而不是在dependencies項塊中implementation時,構建的 JAR 文件包含所有依賴項 JARs 的全部內容。

這里的問題是您的jar任務配置確實從依賴項 JARs 中獲取了所有內容,包括。 他們的META-INF/目錄文件。 其中一些依賴項 JARs 似乎已簽名,因此在其META-INF/目錄中包含數字簽名 - 也由您的jar任務復制。 當運行java -jar …時,這些簽名會妨礙並導致 class not found 錯誤(即使 classJAR 中)。

一個簡單的解決方法是在創建 JAR 文件時排除簽名:

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

將 go 歸功於此 SO answer

這是一個將 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.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM