NoClassDefFoundError at runtime with Gradle

I use gradle as a JavaFX plugin. Everything works fine even after creating and running execcutable when distributing /, with the exception of one class: CloseableHttpClient

For several purposes, I create the following object:

 CloseableHttpClient client = HttpClients.createDefault(); 

Running the program in the IDE is not a problem, everything works fine. But if I create and try to run the .exe file, I get the following Throwable -StackTrace:

 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)... 

I really don't get it. How can it be that this class is not found, but all my other classes?

My build.gradle file:

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

Please write a comment if you need more information. thanks.

+7
java noclassdeffounderror throwable gradle
source share
1 answer

This is a good question I came across right now, exploring examples of many ways that Java developers can enjoy a class :-)

I started with the minimal version of your build.gradle (including only what is directly relevant), in particular:

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

In this context, the My 'Main' class uses your sample code, that is:

 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(); } } 

At this point I can run gradle clean build and then java -jar build/libs/33106520.jar (my project was named after this StackOverflow question) and I see the following:

 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) 

This is subtly different from your error, but before we break it down and reproduce it, let me emphasize something: both this error and what you see are called at runtime when the class loader cannot find the class that it needed, There's a pretty good blog post here with more details on the difference between class classes and runtime classes.

If I run gradle dependencies , I can see the runtime dependencies for my project:

 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 

I manually added them one by one to my classpath. (For reference, this is usually not considered good practice, but for the experiment I copied these banks to the build/libs folder and ran java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main . Interestingly, this Failed to reproduce your exact problem. Recall:

  • Without org.apache.httpcomponents:httpclient available at run time, we fail because the HttpClients jar HttpClients not found.
  • With org.apache.httpcomponents:httpclient:4.5.1 available at runtime, your problem doesn't show up - and I notice that the class your assembly doesn't find ( org.apache.http.conn.ssl.SSLConnectionSocketFactory ) is part of the same Apache library, which is very suspicious.

My suspicion is that your runtime path contains a different version of the apache httpclient library. Since there are all versions of lotta there, I am not going to test each combination, so instead you will leave the following advice to you.

  • If you want to fully understand the root cause of your problem, then determine exactly which banks (including their versions) are present in your path to the runtime classes, including any banks that are packed inside yours if you create (more on this in paragraph 3) . It would be great if you shared these details here; analysis of the root causes usually helps everyone better understand :-)
  • If possible, avoid using dependencies with the compile fileTree(dir: 'lib', include: ['*.jar']) . Repository-based managed dependencies such as Maven or JCenter make it much easier to work with sequences than dependencies in a random directory. If these are internal libraries that you don’t want to publish to the open source artifact repository, it might be worth creating a local Nexus instance or similar.
  • Consider creating a “thick jar” instead of a “thin jar” —this means that all time-dependent packages are packaged in the jar you create. There's a nice Shadow plugin for Gradle that I would recommend - with this in place in my build.gradle and running gradle clean shadow , I managed to run java -jar just fine, without having to manually add anything to my classpath.
+7
source share

All Articles