एक JAR के भीतर JAR सहित Classpath


134

क्या जावा को निर्दिष्ट करना संभव classpathहै जिसमें एक JAR फाइल शामिल है जो एक अन्य JAR फाइल के भीतर है?

जवाबों:


94

यदि आप एक एकल जार बनाने की कोशिश कर रहे हैं जिसमें आपका एप्लिकेशन और इसकी आवश्यक लाइब्रेरी शामिल हैं, तो ऐसा करने के दो तरीके हैं (जो मुझे पता है)। पहला वन-जार है , जो जार के नेस्टिंग की अनुमति देने के लिए एक विशेष क्लास लोडर का उपयोग करता है। दूसरा UberJar , या Shade है ) है, जिसमें शामिल लाइब्रेरीज़ में विस्फोट होता है और सभी कक्षाओं को शीर्ष-स्तरीय जार में रखा जाता है।

मुझे यह भी उल्लेख करना चाहिए कि UberJar और Shade क्रमशः Maven1 और Maven2 के लिए प्लगइन्स हैं। जैसा कि नीचे उल्लेख किया गया है, आप असेंबली प्लगइन का उपयोग भी कर सकते हैं (जो वास्तव में बहुत अधिक शक्तिशाली है, लेकिन ठीक से कॉन्फ़िगर करने के लिए बहुत कठिन है)।


81
तो यहां हम 5 साल बाद हैं। ऐसा लग रहा है कि यह अभी भी सच है। बहुत दुखद :(
T3rm1

3
अब के दिनों में मुझे जो सबसे अच्छा तरीका पता है, वह है इंटेलीज जार आर्टवर्क का उपयोग करना। यह आश्रित जार से सभी वर्गों को निकालता है और उन्हें आपके एक जार में डालता है।
enl8enmentnow

2
कुछ स्थितियों में ऐसा संभव नहीं है जब आपके जेसीई कार्यान्वयन का उपयोग करते हुए
बाउंसीकैसल

1
@ BrainSlugs83 ... आप क्या करने की कोशिश कर रहे हैं? मुझे लगता है कि वन-जार का क्लास लोडर और पैकर अभी भी जार के भीतर जार (जावा एसई के लिए) परियोजनाओं को शामिल करने का जवाब है। UberJar का उपयोग करना आपके जार में क्लास फ़ाइलों को निकालने से समस्या को समाप्त करता है।
स्टीव मोयर

1
UberJar लिंक को लॉगिन क्रेडेंशियल की आवश्यकता है। क्या कोई उत्तराधिकारी वेबपेज है?
थॉमस वेलर

50

आप उन "JAR सामग्री विस्फोट" समाधान का उपयोग नहीं करना चाहते हैं। वे निश्चित रूप से सामान को देखना कठिन बनाते हैं (चूंकि सब कुछ एक ही स्तर पर विस्फोट हो जाता है)। इसके अलावा, नामकरण संघर्ष हो सकता है (ऐसा नहीं होना चाहिए अगर लोग उचित पैकेज का उपयोग करते हैं, लेकिन आप हमेशा इसे नियंत्रित नहीं कर सकते हैं)।

जो सुविधा आप चाहते हैं, वह शीर्ष 25 Sun RFEs में से एक है : RFE 4648386 , जिसे सूर्य, उनके अनंत ज्ञान में, निम्न प्राथमिकता के रूप में नामित किया गया है। हम केवल आशा कर सकते हैं कि सूर्य जाग जाए ...

इस बीच, सबसे अच्छा समाधान जो मुझे आया है (जो मैं चाहता हूं कि सूर्य जेडीके में कॉपी होगा) कस्टम क्लास लोडर जारक्लासलाडर का उपयोग करना है ।


4
नामकरण संघर्ष वास्तव में लॉग 4 जे कॉन्फ़िगरेशन और लाइसेंस ग्रंथों जैसे सामान के साथ होने की गारंटी है।
माइकल बोर्गवर्ड

1
अफसोस की बात है कि JarClassLoader GPLv3 / Commercial है, इसलिए संभवत: इसे "सन (अब ऑरेकल)" द्वारा कॉपी नहीं किया जाएगा, और इसका व्यावसायिक उपयोग तब तक नहीं किया जा सकता जब तक कि आपके पास कुछ खरीदने के लिए आंतरिक राजनीतिक दबदबा और समय न हो। हालांकि मैं सहमत हूं कि वर्तमान निर्देशिका पर बार कि जार एक बुरी चीज है।
गस

इस उत्तर में विचार के लिए +1 (हालांकि मैं स्वयं उत्तर नहीं + 1 करूंगा): आप किसी भी हस्ताक्षरित JAR फ़ाइल को फिर से पैकेज नहीं कर सकते हैं, इसलिए इस तकनीक का उपयोग कई स्थितियों में नहीं किया जा सकता है (जैसे जावा का activation.jar)।
क्रिस्टोफर शुल्त्स

31

कुछ शोध के बाद मुझे ऐसी विधि मिली है जिसमें मावेन या किसी तीसरे पक्ष के विस्तार / कार्यक्रम की आवश्यकता नहीं है।

आप अपनी अभिव्यक्ति फ़ाइल में "क्लास-पाथ" का उपयोग कर सकते हैं।

उदाहरण के लिए:

मैनिफ़ेस्ट फ़ाइल बनाएँ MANIFEST.MF

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

अपनी सभी कक्षाओं को संकलित करें और चलाएं jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

cसंग्रह बनाने के लिए खड़ा है fइंगित करता है कि आप फ़ाइल निर्दिष्ट करना चाहते हैं vवर्बोज़ इनपुट के लिए mइसका मतलब है कि हम कस्टम मैनिफ़ेस्ट फ़ाइल पास करेंगे

सुनिश्चित करें कि आपने जार पैकेज में लिब को शामिल किया है। आपको सामान्य तरीके से जार चलाने में सक्षम होना चाहिए।

इसके आधार पर: http://www.ibm.com/developerworks/library/j-5things6/

आपके द्वारा यहां खोजे जाने वाले वर्ग-पथ के बारे में अन्य सभी जानकारी की आवश्यकता है


19
यह उत्तर काम नहीं करता है। ऑरेकल डॉक से (ऊपर केले से जुड़ा हुआ): "क्लास-पाथ हेडर स्थानीय नेटवर्क पर कक्षाओं या JAR फ़ाइलों को इंगित करता है, JAR फाइल के भीतर JAR फाइलें नहीं"
sebnukem

कुछ भी ज्ञात है कि क्या इसका उपयोग एंड्रॉइड सेटिंग में भी किया जा सकता है।
मोस्टकोस्की

2
यह निष्पादन योग्य जार परिदृश्य (परीक्षण) के लिए काम करता है, लेकिन यह तब काम नहीं कर सकता जब आप किसी लाइब्रेरी जार में जार को शामिल करना चाहते हैं।
साइकिह

5
अरे नहीं, यह काम नहीं करता है, एक बार जब मैं चला custom_lib.jarगया, तो जार अब निष्पादित नहीं किया जा सकता है :(
साइकिह

क्लास-पाथ में कई जार कैसे निर्दिष्ट किए जा सकते हैं?
अभिषेक तिवारी

22

Zipgroupfileset टैग का उपयोग करें (एक fileset टैग के रूप में एक ही गुण का उपयोग करता है ); यह निर्देशिका में सभी फ़ाइलों को अनज़िप करेगा और आपकी नई संग्रह फ़ाइल में जोड़ देगा। अधिक जानकारी: http://ant.apache.org/manual/Tasks/zip.html

जार-ए-जार समस्या के आसपास पाने के लिए यह एक बहुत ही उपयोगी तरीका है - मुझे पता है क्योंकि मैंने इस सटीक स्टैकऑवरफ्लो प्रश्न को हल कर दिया है जबकि यह जानने की कोशिश कर रहा हूं कि क्या करना है। यदि आप चींटी या जार के एक फ़ोल्डर को चींटी के साथ अपने एक निर्मित जार में पैकेज करना चाहते हैं, तो यह सब क्लासपाथ या थर्ड-पार्टी प्लगइन सामान के बारे में भूल जाएं, आपको बस इतना करना होगा (चींटी में):

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

8

यदि आप चींटी के साथ निर्माण कर रहे हैं (मैं ग्रहण से चींटी का उपयोग कर रहा हूं), तो आप उन्हें जोड़ने के लिए चींटी को कहकर अतिरिक्त जार फ़ाइलों को जोड़ सकते हैं ... जरूरी नहीं कि यदि आपके पास कई लोगों द्वारा बनाई गई परियोजना है, तो सबसे अच्छी विधि है लेकिन यह काम करती है एक व्यक्ति परियोजना के लिए और आसान है।

उदाहरण के लिए मेरा .jar फ़ाइल बनाने वाला लक्ष्य था:

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

मैंने इसे बनाने के लिए सिर्फ एक लाइन जोड़ी:

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

कहाँ पे

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

बाहरी जार के साथ dir था। और बस...


6

अपनी कक्षा लोडर लिखे बिना नहीं। आप जार के क्लासपाथ में जार जोड़ सकते हैं, लेकिन उन्हें सह-स्थित होना चाहिए, मुख्य जार में निहित नहीं।


2

आपको ऐसा करने के लिए एक कस्टम क्लास-लोडर बनाने की आवश्यकता है या यह समर्थन करने वाला एक तृतीय-पक्ष लाइब्रेरी है। आपका सबसे अच्छा शर्त रन से जार निकालने और उन्हें क्लासपाथ में जोड़ना है (या उन्हें पहले से ही क्लासथ में जोड़ा गया है)।


2

मैं अपने जावा बिल्ड के लिए मावेन का उपयोग करता हूं जिसमें एक प्लगइन होता है जिसे मावेन असेंबली प्लगइन कहा जाता है ।

यह आपके पूछने पर क्या करता है, लेकिन कुछ अन्य सुझावों का वर्णन है - अनिवार्य रूप से सभी आश्रित जार को विस्फोट करना और उन्हें एक जार में पुन: संयोजित करना


मावेन असेंबली प्लगइन का उपयोग करने के लिए बहुत दर्दनाक है ... उबेरजर और शेड मावेन 1 और मावेन 2 प्लगइन्स हैं (एक तथ्य जो मुझे ऊपर उल्लेख करना चाहिए था, और अब ऐसा करेंगे)
स्टीव मोयर

2

यदि आपके पास आईडीई है, तो आपको अपने JAR को निर्यात करने और "पैकेज आवश्यक लाइब्रेरी को जनरेटेड JAR में" चुनने की आवश्यकता है। ग्रहण स्वचालित रूप से आवश्यक JAR को उत्पन्न JAR में जोड़ देगा और साथ ही कुछ ग्रहण कस्टम क्लास लोडर भी उत्पन्न करेगा जो इन JAR को स्वचालित रूप से लोड करता है।


1

मैं एक ही स्तर पर सभी फ़ाइलों को निकालने की सलाह देने वाला था, फिर परिणाम से एक जार बनाने के लिए, क्योंकि पैकेज सिस्टम को उन्हें बड़े करीने से अलग रखना चाहिए। यह मैनुअल तरीका होगा, मुझे लगता है कि स्टीव द्वारा बताए गए उपकरण अच्छी तरह से करेंगे।



1

यदि आप ग्रहण का उपयोग कर रहे हैं, तो एक बहुत ही आसान तरीका है।

अपनी परियोजना को "रननेबल" जार फ़ाइल के रूप में निर्यात करें (ग्रहण के भीतर राइट-क्लिक प्रोजेक्ट फ़ोल्डर, "निर्यात करें ..." चुनें)। जब आप निर्यात सेटिंग्स को कॉन्फ़िगर करते हैं, तो "जार में आवश्यक लाइब्रेरी निकालें" का चयन करना सुनिश्चित करें। ध्यान रखें, "एक्सट्रैक्ट ..." का चयन करें न कि "पैकेज के लिए आवश्यक लाइब्रेरी ..."।

अतिरिक्त रूप से : आपको अपनी निर्यात सेटिंग में रन-कॉन्फ़िगरेशन का चयन करना होगा। तो, आप हमेशा किसी वर्ग में एक खाली मुख्य () बना सकते हैं और इसे अपने रन कॉन्फ़िगरेशन के लिए उपयोग कर सकते हैं।

वैसे भी, यह 100% समय काम करने की गारंटी नहीं है - जैसा कि आप एक पॉप-अप संदेश देखेंगे जो आपको यह सुनिश्चित करने के लिए कहेंगे कि आप उन जार फ़ाइलों के लाइसेंस की जांच कर रहे हैं जिनमें आप शामिल हैं और हस्ताक्षर फ़ाइलों की प्रतिलिपि नहीं बनाने के बारे में कुछ। हालांकि, मैं वर्षों से ऐसा कर रहा हूं और मुझे कभी समस्या नहीं हुई।


0

Uber-dir में काम करना मेरे लिए काम करता है क्योंकि हम सभी को रूट: \ java का उपयोग करना चाहिए और संस्करण के साथ संकुल में आउटलेट कोड होते हैं। यानी ca.tecreations-1.0.0। साइनिंग ठीक है क्योंकि जार अपने डाउनलोड किए गए स्थान से बरकरार हैं। तृतीय पक्ष के हस्ताक्षर बरकरार हैं, c: \ java तक निकालें। वहाँ मेरी परियोजना dir है। लॉन्चर से रन करें इसलिए java -cp c: \ java Launcher


तो जार में c: \ java \ jars। स्रोत, बायनेरिज़ और संसाधन c: \ java में। बैकअप, गुण, कीस्टोरी_पाइप को छोड़ दें। C: \ java के लिए अनपैक करें और क्लासपैथ बनाने वाले टूल के साथ चलें, इसलिए शायद ca.tecreations.system.tools.SystemTool या तुलनीय जावा क्लास। निष्पादित करें।
टिम डी विर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.