2015-10-13 173 views
7

我使用gradle作爲JavaFX插件。 一切,即使在分佈/建設和運行過程中出現的excecutable後完美的作品,除了有一類:CloseableHttpClientNoClassDefFoundError在運行時使用Gradle

用於多種用途創建下列對象是這樣的:

CloseableHttpClient client = HttpClients.createDefault(); 

運行的程序IDE沒有問題,一切正常。但是,如果我建立並嘗試運行.exe文件,文件我得到以下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)... 

我真的不明白。怎麼可能只是這個班級沒有找到,但我所有的其他班級呢?

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

請寫一個評論,如果您需要了解更多信息。謝謝。

+0

請分享您的build.gradle文件。 – Opal

+0

@Opal完成。仍然沒有找到解決方案:/ – jntme

+0

分發中的apache jar嗎?它是否包含缺少的課程? –

回答

7

這是一個很好的問題,這是我穿過剛纔,而研究的許多方面的例子Java開發人員可以結束了類路徑樂趣:-)

我開始使用您的build.gradle的最小版本出來(只包括什麼是直接相關的),具體如下:

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

我的「主」類,在這種情況下,使用您的代碼示例,即:

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

在這一階段,我可以運行gradle clean build其次java -jar build/libs/33106520.jar(我的計劃是這樣的StackOverflow問題而得名),我看到:

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) 

這是你的錯誤微妙的不同,但是我們挖掘和重現之前,我要強調的東西:這個錯誤和你看到的錯誤都是在類加載器無法找到它需要的類時在運行時造成的。有相當不錯的博客文章here,詳細介紹了編譯時類路徑和運行時類路徑之間的區別。

如果我跑gradle dependencies我可以看到我的項目在運行時依賴:

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 

我手動添加這些一個接一個到我的運行時類路徑。 (根據記錄,這通常不被認爲是好的做法;但爲了實驗的目的,我將這些罐子複製到了我的build/libs文件夾中,並與java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main一起運行。有趣的是,這無法重現您確切的問題。回顧:

  • 沒有org.apache.httpcomponents:httpclient在運行時可用,那麼我們就失敗,因爲HttpClients罐子找不到
  • 隨着org.apache.httpcomponents:httpclient:4.5.1在運行時可用,那麼你的問題並不明顯 - 我注意類的構建失敗。找到(org.apache.http.conn.ssl.SSLConnectionSocketFactory)是這個相同的Apache庫的一部分,這確實是非常可疑的。

我懷疑你的運行時類路徑是否包含Apache httpclient庫的不同版本。由於這裏有很多lotta版本,我不打算測試每一個組合,所以我會給你留下以下建議。

  1. 如果你想全面瞭解您的問題的根本原因,然後確定究竟這罐(包括它們的版本)存在於您的錯誤的情況下運行時類路徑,包括如果包裝內你的任何廣口瓶你正在創建一個胖罐子(更多關於這點的第3點)。如果你在這裏分享這些細節,那會很棒;根本原因分析通常可以幫助大家更好地理解:-)
  2. 如有可能,請避免以compile fileTree(dir: 'lib', include: ['*.jar'])的方式使用依賴關係。基於存儲庫(例如Maven或JCenter)的託管依賴關係比隨機目錄中的依賴關係更易於一致地工作。如果這些內部庫是您不想發佈到開源工件存儲庫的,那麼可能需要設置本地Nexus實例或類似工具。
  3. 考慮生成一個「胖jar」而不是「thin jar」 - 這意味着所有的運行時依賴包都打包在你生成的jar中。有一個很好的Shadow plugin for Gradle,我建議 - 這在我的build.gradle,並在運行gradle clean shadow,我能夠運行java -jar就好了,無需手動添加任何東西到我的類路徑。
+0

我得到了'java.lang.NoClassDefFoundError:org/apache/http/config/Lookup'。我一直在Eclipse的'Maven Dependencies'下查找Apache Http JAR(httpclient,httpcore)中這個類的存在,但沒有找到它們。意識到maven選擇從父POM中解析一些其他版本的'httpcore',而不是'httpcore'版本,它是'httpclient'的直接依賴.Had給出了一個明確的'httpcore'版本,它與版本相同'httpclient'的直接依賴關係。 – user104309

相關問題