简体   繁体   中英

“Could not find or load main class” error for Gradle-generated Scala JAR

After much research, I can't seem to get to the root of a problem I am having in generating a runnable Scala jar file using Gradle. I'm overriding the 'jar' Gradle task to create a jar file (dependencies included) that executes starting from my main class file. However, whenever I run it, regardless of what I use for a Main-Class attribute, the console throws a "Could not find or load main class" error. Here's what I have so far:

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
}

apply plugin: 'java'
apply plugin: 'scala'
apply plugin: 'application'

repositories {
    mavenCentral()
    // some other repos
}

version = '1.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8

mainClassName = "com.test.Main"

dependencies {
    // my dependencies
}

jar {
    zip64 = true

    manifest {
        attributes "Main-Class": "$mainClassName"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

src/main/scala/com/test/Main.scala

package com.test

object Main {
  def main(args: Array[String]): Unit = {
    print("Hello world");
  }
}

In fact, when I run "java tf test.jar", it shows "com/test/Main.class" in the root of the jar! Am I missing some important class path info or something? I'm running Java 1.8 on macOS Sierra using Gradle 3.5. Any help is appreciated. Thanks!

I had a similar problem and it turns out that my META-INF folder inside my jar file contains a few RSA, SF, and DSA files.

Once I excluded them, it worked!

here is how to based on your jar declaration

jar {
    zip64 = true

    manifest {
        attributes "Main-Class": "$mainClassName"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) 
    }
    exclude ('META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA')
}

You can use the Shadow Jar Plugin instead of your own jar definition.

Benefits of Shadow

Shadowing a project output has 2 major use cases:

  • Creating an executable JAR distribution
  • Bundling and relocating common dependencies in libraries to avoid classpath conflicts

Basic setup:

shadowJar {
    baseName = 'your-app'
    classifier = 'all'
    version = version
    configurations = [project.configurations.compile]
}

jar {
    manifest {
        attributes 'Main-Class': 'com.test.Main'
    }
}

You can use the new syntax of Gradle Plugins:

plugins {
    id 'java'
    id 'scala'
    id 'application'
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM