2015-10-13 20 views
7

Tôi đang sử dụng gradle làm plugin JavaFX. Tất cả mọi thứ hoạt động hoàn hảo ngay cả sau khi xây dựng và runnig các excecutable tại phân phối/, trừ trường hợp một lớp: CloseableHttpClientNoClassDefFoundError at Runtime with Gradle

Đối với nhiều mục đích tôi tạo ra các đối tượng sau đây như thế này:

CloseableHttpClient client = HttpClients.createDefault(); 

Chạy chương trình trong IDE là không có vấn đề, tất cả mọi thứ hoạt động tốt. Nhưng nếu tôi xây dựng và cố gắng chạy .exe-File tôi nhận được Throwable -StackTrace sau:

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

Tôi thật sự không hiểu điều đó. Làm thế nào nó có thể được rằng chỉ lớp này không được tìm thấy, nhưng tất cả các lớp học khác của tôi làm gì?

tập tin build.gradle của tôi:

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

Hãy viết một bình luận nếu bạn cần thêm thông tin. Cám ơn.

+0

Vui lòng chia sẻ tệp build.gradle của bạn. – Opal

+0

@Opal hoàn tất. vẫn không tìm thấy giải pháp:/ – jntme

+0

Bình apache trong bản phân phối chưa? Nó có chứa lớp bị thiếu không? –

Trả lời

7

đó là một câu hỏi hay, mà tôi đi qua chỉ là bây giờ trong khi nghiên cứu ví dụ trong nhiều cách các nhà phát triển Java có thể kết thúc với đường dẫn lớp vui vẻ :-)

tôi bắt đầu với một phiên bản tối thiểu của build.gradle của bạn (chỉ bao gồm những gì liên quan trực tiếp), cụ thể:

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

My lớp 'Main', trong bối cảnh này, sử dụng mã ví dụ của bạn, ví dụ:

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

ở giai đoạn này , Tôi có thể chạy gradle clean build tiếp theo java -jar build/libs/33106520.jar (dự án của tôi được đặt tên sau khi câu hỏi StackOverflow này) và tôi thấy điều này:

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) 

Đây là một cách tinh tế khác nhau từ lỗi của bạn, nhưng trước khi chúng tôi đào và tái sản xuất đó, tôi xin nhấn mạnh một cái gì đó : cả lỗi này và lỗi mà bạn đang gặp phải là do thời gian chạy khi trình nạp lớp không thể tìm thấy một lớp mà nó cần. Có một bài đăng trên blog khá tốt here với một số chi tiết khác về sự khác biệt giữa classpath thời gian biên dịch và classpath thời gian chạy.

Nếu tôi chạy gradle dependencies tôi có thể thấy sự phụ thuộc thời gian chạy cho dự án của tôi:

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 

tôi thêm những bằng tay một-by-one vào classpath thời gian chạy của tôi. (Đối với hồ sơ, điều này thường không được coi là thực hành tốt, nhưng vì lợi ích của thử nghiệm, tôi đã sao chép các lọ này vào thư mục build/libs của mình và chạy với java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main. Điều thú vị là, điều này không thể tái tạo vấn đề chính xác của bạn. tóm tắt:

  • Without org.apache.httpcomponents:httpclient sẵn tại thời gian chạy, sau đó chúng ta thất bại vì HttpClients jar không tìm thấy
  • với org.apache.httpcomponents:httpclient:4.5.1 sẵn tại thời gian chạy, sau đó vấn đề của bạn không biểu hiện - và tôi lưu ý rằng lớp xây dựng của bạn thất bại. để tìm (org.apache.http.conn.ssl.SSLConnectionSocketFactory) là một phần của cùng thư viện Apache này, điều này thực sự rất đáng ngờ.

nghi ngờ của tôi là sau đó rằng classpath thời gian chạy của bạn có chứa một phiên bản khác nhau của Apache httpclient thư viện. Vì có một phiên bản lotta toàn bộ ra khỏi đó, tôi sẽ không kiểm tra mọi sự kết hợp duy nhất, vì vậy tôi sẽ để lại cho bạn những lời khuyên sau đây.

  1. Nếu bạn muốn hiểu đầy đủ về nguyên nhân gốc rễ của vấn đề của bạn, sau đó xác định chính xác mà lọ (bao gồm cả các phiên bản của họ) có mặt trong lỗi hợp cụ thể thời gian chạy classpath của bạn, bao gồm bất kỳ lọ được đóng gói bên trong của bạn nếu bạn đang tạo ra một lọ chất béo (nhiều hơn về điều này ở điểm 3). Thật tuyệt vời nếu bạn chia sẻ những chi tiết này ở đây; phân tích nguyên nhân gốc thường giúp mọi người hiểu rõ hơn :-)
  2. Nếu có thể, tránh sử dụng các phụ thuộc theo cách compile fileTree(dir: 'lib', include: ['*.jar']). Các phụ thuộc được quản lý dựa trên một kho lưu trữ như Maven hoặc JCenter dễ dàng hơn nhiều khi làm việc một cách nhất quán hơn các phụ thuộc trong một thư mục ngẫu nhiên. Nếu đây là các thư viện nội bộ mà bạn không muốn xuất bản lên kho lưu trữ phần mềm nguồn mở, thì có thể đáng giá thiết lập một phiên bản Nexus cục bộ hoặc tương tự.
  3. Cân nhắc tạo ra "lọ chất béo" thay vì "lọ mỏng" - điều này có nghĩa là tất cả các phụ thuộc thời gian chạy được đóng gói trong bình mà bạn xây dựng. Có một số Shadow plugin for Gradle tốt mà tôi muốn giới thiệu - với điều này tại chỗ trong build.gradle của tôi và chạy gradle clean shadow, tôi đã có thể chạy java -jar tốt mà không cần phải thêm bất kỳ thứ gì vào đường dẫn lớp của mình theo cách thủ công.
+0

Tôi nhận được 'java.lang.NoClassDefFoundError: org/apache/http/config/Lookup'. Tôi tiếp tục tìm kiếm sự hiện diện của lớp này bên trong Apache Http JARs (httpclient, httpcore) trong phần 'Maven Dependencies' trong Eclipse và không tìm thấy chúng. Nhận ra rằng maven đã chọn để giải quyết một số phiên bản khác của 'httpcore' từ cha mẹ POM thay vì phiên bản' httpcore' là một sự phụ thuộc trực tiếp của 'httpclient'.Had để đưa ra một phiên bản' httpcore' rõ ràng khớp với phiên bản tương tự như phiên bản của phiên bản phụ thuộc trực tiếp của 'httpclient'. – user104309

Các vấn đề liên quan