J'utilise gradle comme plugin JavaFX. Tout fonctionne parfaitement même après la construction et l'exécution de l'exécutable à distribution /, sauf avec une classe: CloseableHttpClient
À plusieurs fins, je crée l'objet suivant comme ceci:
CloseableHttpClient client = HttpClients.createDefault();
L'exécution du programme dans le IDE ne pose aucun problème, tout fonctionne bien. Mais si je crée et essaie d'exécuter le fichier .exe, j'obtiens le Throwable
- StackTrace suivant:
Java.lang.NoClassDefFoundError: Could not initialize class org.Apache.http.conn.ssl.SSLConnectionSocketFactory
at org.Apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.Java:955)
at org.Apache.http.impl.client.HttpClients.createDefault(HttpClients.Java:58)
at ch.itcb.tools.lom.util.JsonSimpleUtil.http(JsonSimpleUtil.Java:29)...
Je ne comprends vraiment pas ça. Comment se fait-il que cette classe ne soit pas trouvée, mais toutes mes autres classes le font?
Mon fichier build.gradle:
apply plugin: 'Java'
apply plugin: 'Eclipse'
apply from: 'javafx.plugin'
sourceCompatibility = 1.8
version = '0.1'
jar {
manifest {
attributes 'Implementation-Title': 'LogoffManager',
'Implementation-Version': version
}
}
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'lib', include: ['*.jar'])
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'org.Apache.httpcomponents:httpclient:4.5.1'
compile 'com.googlecode.json-simple:json-simple:1.1'
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
test {
systemProperties 'property': 'value'
}
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}
Veuillez écrire un commentaire si vous avez besoin de plus d'informations. THX.
c'est une bonne question, que j'ai rencontrée tout à l'heure en recherchant des exemples de nombreuses façons Java peuvent se retrouver avec un chemin de classe amusant :-)
J'ai commencé avec une version minimale de votre build.gradle (y compris uniquement ce qui est directement pertinent), en particulier:
plugins {
id 'Java'
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
jar {
manifest {
attributes 'Main-Class': 'com.oliverlockwood.Main'
}
}
dependencies {
compile 'org.Apache.httpcomponents:httpclient:4.5.1'
}
Dans ce contexte, ma classe `` principale '' utilise votre exemple de code, à savoir:
package com.oliverlockwood;
import org.Apache.http.impl.client.CloseableHttpClient;
import org.Apache.http.impl.client.HttpClients;
public class Main {
public static void main(String[] args) {
CloseableHttpClient client = HttpClients.createDefault();
}
}
À ce stade, je peux exécuter gradle clean build
Suivi de Java -jar build/libs/33106520.jar
(Mon projet a été nommé d'après cette question StackOverflow) et je vois ceci:
Exception in thread "main" Java.lang.NoClassDefFoundError: org/Apache/http/impl/client/HttpClients
at com.oliverlockwood.Main.main(Main.Java:8)
Caused by: Java.lang.ClassNotFoundException: org.Apache.http.impl.client.HttpClients
at Java.net.URLClassLoader.findClass(URLClassLoader.Java:381)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:331)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
Ceci est subtilement différent de votre erreur, mais avant de creuser et de reproduire cela, permettez-moi de souligner quelque chose: cette erreur et celle que vous voyez sont causées au moment de l'exécution lorsque le chargeur de classe n'est pas en mesure de trouver une classe dont il a besoin. Il y a un bon article de blog ici avec plus de détails sur la différence entre le chemin de classe au moment de la compilation et les chemins de classe au moment de l'exécution.
Si j'exécute gradle dependencies
, Je peux voir les dépendances d'exécution de mon projet:
runtime - Runtime classpath for source set 'main'.
\--- org.Apache.httpcomponents:httpclient:4.5.1
+--- org.Apache.httpcomponents:httpcore:4.4.3
+--- commons-logging:commons-logging:1.2
\--- commons-codec:commons-codec:1.9
Je les ai ajoutés manuellement un par un à mon chemin de classe d'exécution. (Pour mémoire, ce n'est généralement pas considéré comme une bonne pratique; mais pour le bien de l'expérience, j'ai copié ces pots dans mon dossier build/libs
Et j'ai couru avec Java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main
. Fait intéressant, ce n'était pas pas en mesure de reproduire votre problème exact. Pour récapituler:
org.Apache.httpcomponents:httpclient
Disponible au moment de l'exécution, nous échouons car le fichier HttpClients
est introuvable.org.Apache.httpcomponents:httpclient:4.5.1
Disponible au moment de l'exécution, votre problème ne se manifeste pas - et je note que la classe que votre génération ne trouve pas (org.Apache.http.conn.ssl.SSLConnectionSocketFactory
) Fait partie de cela même bibliothèque Apache , ce qui est en effet très suspect.Je soupçonne alors que votre chemin de classe d'exécution contient une version différente de la bibliothèque Apache httpclient. Comme il existe de nombreuses versions, je ne vais pas tester chaque combinaison, je vous laisse donc les conseils suivants.
compile fileTree(dir: 'lib', include: ['*.jar'])
. Les dépendances gérées basées sur un référentiel tel que Maven ou JCenter sont beaucoup plus faciles à utiliser avec cohérence que les dépendances dans un répertoire aléatoire. S'il s'agit de bibliothèques internes que vous ne souhaitez pas publier dans un référentiel d'artefacts open source, il peut être utile de configurer une instance Nexus locale ou similaire.build.gradle
, Et en exécutant gradle clean shadow
, J'ai pu exécuter Java -jar
Très bien sans avoir à ajouter manuellement quoi que ce soit à mon chemin de classe.