Classpath bao gồm JAR trong JAR


134

Có thể chỉ định một Java classpathbao gồm một tệp JAR có trong một tệp JAR khác không?

Câu trả lời:


94

Nếu bạn đang cố gắng tạo một bình chứa ứng dụng của mình và các thư viện cần thiết, có hai cách (mà tôi biết) để làm điều đó. Đầu tiên là One-Jar , sử dụng một trình nạp lớp đặc biệt để cho phép lồng các lọ. Thứ hai là UberJar , (hoặc Bóng râm ), làm nổ tung các thư viện đi kèm và đặt tất cả các lớp vào bình cấp cao nhất.

Tôi cũng nên đề cập rằng UberJar và Shadow tương ứng là các plugin cho Maven1 và Maven2. Như đã đề cập dưới đây, bạn cũng có thể sử dụng plugin lắp ráp (trong thực tế mạnh hơn nhiều, nhưng khó hơn nhiều để cấu hình đúng cách).


81
Vì vậy, chúng tôi ở đây, 5 năm sau. Có vẻ như điều này vẫn đúng. Rất buồn :(
T3rm1

3
Cách tốt nhất mà tôi biết bây giờ là sử dụng tạo tác của IntelliJ jar. Nó trích xuất tất cả các lớp từ các lọ phụ thuộc và đặt chúng vào một lọ của bạn.
ext8enmentnow

2
Điều đó không thể xảy ra trong một số trường hợp như khi bạn sử dụng các triển khai JCE như BouncyCastle cần được ký
mắt

1
@ BrainSlugs83 ... Bạn đang cố gắng làm gì? Tôi nghĩ rằng trình nạp lớp và đóng gói của One-Jar vẫn là câu trả lời để bao gồm một Jar trong các dự án Jar (cho Java SE). Sử dụng UberJar giúp loại bỏ sự cố bằng cách trích xuất các tệp lớp vào Jar của bạn.
Steve Moyer

1
Liên kết UberJar cần thông tin đăng nhập. Có bất kỳ trang web kế nhiệm?
Thomas Weller

50

Bạn KHÔNG muốn sử dụng các giải pháp "nổ nội dung JAR" đó. Họ chắc chắn làm cho khó nhìn thấy các công cụ hơn (vì mọi thứ đều bùng nổ ở cùng cấp độ). Hơn nữa, có thể có xung đột đặt tên (không nên xảy ra nếu mọi người sử dụng các gói phù hợp, nhưng bạn không thể luôn kiểm soát điều này).

Tính năng mà bạn muốn là một trong 25 RFE mặt trời hàng đầu : RFE 4648386 , mà Sun, trong trí tuệ vô hạn của họ, được chỉ định là ưu tiên thấp. Chúng ta chỉ có thể hy vọng rằng Mặt trời thức dậy ...

Trong khi đó, giải pháp tốt nhất mà tôi đã gặp (mà tôi ước rằng Sun sẽ sao chép trong JDK) là sử dụng trình tải lớp tùy chỉnh JarClassLoader .


4
Việc đặt tên xung đột thực sự gần như được đảm bảo xảy ra với những thứ như cấu hình log4j và văn bản giấy phép.
Michael Borgwardt

1
Đáng buồn là JarClassLoader là GPLv3 / thương mại nên có lẽ nó sẽ không bị "sao chép bởi mặt trời (bây giờ là tiên tri)" và không thể được sử dụng thương mại trừ khi bạn có đầu mối chính trị nội bộ và thời gian để mua thứ gì đó. Tuy nhiên, tôi đồng ý rằng các lọ mà barf trong thư mục hiện tại là một điều xấu.
Gus

+1 cho ý tưởng trong câu trả lời này (mặc dù tôi sẽ không là 1 câu trả lời): bạn không thể đóng gói lại bất kỳ tệp JAR nào đã ký, vì vậy kỹ thuật này không thể được sử dụng trong nhiều tình huống (ví dụ: Java activation.jar).
Christopher Schultz

31

Sau một số nghiên cứu, tôi đã tìm thấy phương pháp không yêu cầu maven hoặc bất kỳ chương trình / phần mở rộng của bên thứ 3 nào.

Bạn có thể sử dụng "Đường dẫn lớp" trong tệp kê khai của mình.

Ví dụ:

Tạo tệp kê khai MANIFEST.MF

Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass

Biên dịch tất cả các lớp của bạn và chạy jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

cviết tắt của tạo lưu trữ fchỉ ra rằng bạn muốn chỉ định tệp vdành cho đầu vào dài dòng mcó nghĩa là chúng tôi sẽ chuyển tệp kê khai tùy chỉnh

Hãy chắc chắn rằng bạn đã bao gồm lib trong gói jar. Bạn sẽ có thể chạy jar theo cách thông thường.

dựa trên: http://www.ibm.com/developerworks/l Library / j-5things6 /

tất cả thông tin khác bạn cần về đường dẫn lớp bạn tìm thấy ở đây


19
Câu trả lời này không hoạt động. từ tài liệu oracle (được liên kết bởi chuối ở trên): "Tiêu đề Đường dẫn lớp trỏ đến các lớp hoặc tệp JAR trên mạng cục bộ, không phải tệp JAR trong tệp JAR"
sebnukem

Bất cứ điều gì biết liệu điều này cũng có thể được sử dụng trong cài đặt Android.
Mostowski sụp đổ

2
Nó hoạt động cho kịch bản jar thực thi (đã thử nghiệm), nhưng nó có thể không hoạt động khi bạn muốn bao gồm một jar trong jar thư viện.
Cychih

5
Ồ không, nó không hoạt động, một khi tôi đã chuyển custom_lib.jarđi, bình không thể được thực thi nữa :(
Cychih

Làm thế nào nhiều lọ có thể được chỉ định trong Đường dẫn lớp?
Abhishek Tiwari

22

Sử dụng các zipgroupfileset thẻ (sử dụng cùng một thuộc tính như một fileset thẻ); nó sẽ giải nén tất cả các tệp trong thư mục và thêm vào tệp lưu trữ mới của bạn. Thêm thông tin: http://ant.apache.org/manual/T task / zip.html

Đây là một cách rất hữu ích để giải quyết vấn đề jar-in-a-jar - tôi biết vì tôi đã googled câu hỏi StackOverflow chính xác này trong khi cố gắng tìm hiểu phải làm gì. Nếu bạn muốn gói một lọ hoặc một thư mục lọ vào một lọ được xây dựng bằng Ant, thì hãy quên tất cả các công cụ bổ trợ của lớp thứ ba hoặc bên thứ ba này, tất cả những gì bạn phải làm là (trong Ant):

<jar destfile="your.jar" basedir="java/dir">
  ...
  <zipgroupfileset dir="dir/of/jars" />
</jar>

8

Nếu bạn đang xây dựng với kiến ​​(Tôi đang sử dụng kiến ​​từ nhật thực), bạn có thể chỉ cần thêm các tệp jar bổ sung bằng cách nói với kiến ​​để thêm chúng ... Không nhất thiết là phương pháp tốt nhất nếu bạn có một dự án được duy trì bởi nhiều người nhưng nó hoạt động cho một người dự án và là dễ dàng.

ví dụ mục tiêu của tôi khi xây dựng tệp .jar là:

<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
    <manifest>
        <attribute name="Author" value="ntg"/>
        ................................
        <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
    </manifest>
</jar>

Tôi chỉ cần thêm một dòng để làm cho nó:

<jar ....">
    <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
    <manifest>
        ................................
    </manifest>
</jar>

Ở đâu

<property name="external-lib-dir" 
          value="C:\...\eclipseWorkspace\Filter\external\...\lib" />

là thư mục với các lọ bên ngoài. Và đó là ...


6

Không phải không viết trình nạp lớp của riêng bạn. Bạn có thể thêm bình vào đường dẫn lớp của bình, nhưng chúng phải được đặt cùng vị trí, không được chứa trong bình chính.


2

Bạn cần xây dựng trình nạp lớp tùy chỉnh để thực hiện việc này hoặc thư viện của bên thứ ba hỗ trợ việc này. Đặt cược tốt nhất của bạn là trích xuất jar từ thời gian chạy và thêm chúng vào đường dẫn lớp (hoặc chúng đã được thêm vào đường dẫn lớp).


2

Tôi sử dụng maven cho các bản dựng java của tôi có một plugin gọi là plugin lắp ráp maven .

Nó thực hiện những gì bạn yêu cầu, nhưng giống như một số gợi ý khác mô tả - về cơ bản làm nổ tung tất cả các lọ phụ thuộc và kết hợp lại chúng vào một bình duy nhất


Plugin lắp ráp Maven khá khó sử dụng ... UberJar và Shadow là các plugin Maven1 và Maven2 (một thực tế tôi nên đã đề cập ở trên, và sẽ làm như vậy ngay bây giờ)
Steve Moyer

2

Nếu bạn có IDE eclpise, bạn chỉ cần xuất JAR của mình và chọn "Gói thư viện cần thiết vào JAR được tạo". nhật thực sẽ tự động thêm các JAR phụ thuộc cần thiết vào JAR được tạo cũng như tạo ra một số trình nạp lớp tùy chỉnh nhật thực tự động tải các JAR này.


1

Tôi đã khuyên nên trích xuất tất cả các tệp ở cùng cấp độ, sau đó để tạo ra một kết quả ngoài kết quả, vì hệ thống gói nên giữ chúng tách biệt gọn gàng. Đó sẽ là cách thủ công, tôi cho rằng các công cụ được chỉ định bởi Steve sẽ làm điều đó một cách độc đáo.



1

Chà, có một cách rất dễ dàng nếu bạn đang sử dụng Eclipse.

Xuất dự án của bạn dưới dạng tệp Jar "Có thể chạy" (nhấp chuột phải vào thư mục dự án từ bên trong Eclipse, chọn "Xuất ..."). Khi bạn định cấu hình cài đặt xuất, hãy đảm bảo chọn "Trích xuất các thư viện cần thiết vào Jar được tạo." Hãy ghi nhớ, chọn "Trích xuất ..." chứ không phải "Gói thư viện cần thiết ...".

Ngoài ra : Bạn phải chọn cấu hình chạy trong cài đặt xuất. Vì vậy, bạn luôn có thể tạo một hàm main () trống trong một số lớp và sử dụng nó cho cấu hình chạy của bạn.

Dù sao, nó không được đảm bảo hoạt động 100% thời gian - vì bạn sẽ nhận thấy một thông báo bật lên cho bạn biết để đảm bảo bạn kiểm tra giấy phép của các tệp Jar bạn bao gồm và một cái gì đó về việc không sao chép tệp chữ ký. Tuy nhiên, tôi đã làm điều này trong nhiều năm và chưa bao giờ gặp phải vấn đề.


0

Trích xuất vào Uber-dir hoạt động với tôi vì tất cả chúng ta nên sử dụng root: \ java và có mã cửa hàng trong các gói có phiên bản. Tức là ca.tecreations-1.0.0. Ký là ổn vì các lọ vẫn còn nguyên từ vị trí tải xuống của họ. Chữ ký của bên thứ 3 còn nguyên vẹn, trích xuất thành c: \ java. Có dự án của tôi. chạy từ launcher để java -cp c: \ java Launcher


Vì vậy, các lọ trong c: \ java \ jars. Nguồn, nhị phân và tài nguyên trong c: \ java. Không bao gồm sao lưu, thuộc tính, keystore_private. Giải nén vào c: \ java và chạy với công cụ tạo đường dẫn lớp, vì vậy có thể ca.tecreations.system.tools.SystemTool hoặc lớp java so sánh. Thực hiện điều đó.
Tim de Vries
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.