web-dev-qa-db-fra.com

Gradle - FatJar - Impossible de trouver ou de charger la classe principale

Je sais que cette question a été beaucoup posée et a beaucoup de réponses, mais je la comprends toujours et je ne comprends pas pourquoi ...

J'essaie de générer un .jar à partir d'un projet avec des dépendances avec gradle.

J'ai une classe src/main/Java/Launcher.Java, dans laquelle j'ai ma méthode main.

il y a mon 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) }
    }
}

J'utilise $>gradle assemble pour générer mon fichier jar Puis $>Java -jar path/to/my/.jar .

Je ne comprends pas pourquoi, quand je regarde dans le .jar, j'ai la classe Launcher et dans META-INF, j'ai le manifeste.

 screenshot

Désolé de toujours poser cette question en 2018, mais je perds la tête en essayant de comprendre ce qui ne va pas. J'espère que quelqu'un aura la réponse!

6
Hadrien

Je reproduis votre question au niveau local.

Il suffit d'ajouter exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' à la tâche jar. 

Cela exclut les signatures de dépendances parasites. 

5
Andreas Volkmann

Vous rencontrez le seul problème majeur lors de la construction d'un fichier JAR FAT:

L'un de vos fichiers JAR source est signé et sa fusion dans un seul gros pot détruit la signature.

Il semble que Java reconnaisse qu'il existe des classes non signées et ignore tout sauf les classes signées. Comme toutes les classes qui n'appartiennent pas à la bibliothèque signée sont non signées (comme votre classe Launcher), elles sont ignorées et peuvent donc # T être chargées.

Dans votre cas, il semble que la dépendance org.bouncycastle:bcprov-jdk15on:1.55 de com.auth0:Java-jwt:3.1.0 soit le fichier jar signé. Parce que mon exemple de projet exécute correctement Launcher lorsque je ne commente pas cette dépendance. 

Bouncy castle est un fournisseur de cryptographie qui requiert une signature valide, sinon il ne fonctionnera pas selon mon expérience. Par conséquent, il est impossible de créer un gros fichier jar pour votre projet contenant uniquement toutes les classes. 

Vous pouvez essayer de créer un gros pot avec tout sauf Bouncycastle et d'expédier Bouncycastle JAR séparément.

Ou un gros fichier jar contenant tous les fichiers JAR requis à l'intérieur (JAR dans le fichier JAR) et utilisant un chargeur de classes spécial capable de charger des classes à l'intérieur d'un tel fichier JAR dans un fichier JAR. Voir par exemple: https://stackoverflow.com/a/33420518/150978

2
Robert

Essayez d’exclure des fichiers .SF .DSA .RSA, exemple ci-dessous, Nipun

J'espère que cela te convient

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'
  }
}
0
Nipun