मावेन-शेड-प्लगइन का उपयोग किस लिए किया जाता है, और आप जावा पैकेजों को स्थानांतरित क्यों करना चाहते हैं?


281

मैंने पाया कि किसी के pom.xml में मावेन-शेड-प्लगइन का उपयोग किया जा रहा है। मैंने पहले कभी भी मावेन-शेड-प्लगइन का उपयोग नहीं किया है (और मैं एक मावेन n00b हूं) इसलिए मैंने इस का उपयोग करने का कारण और यह क्या करता है, इसे समझने की कोशिश की।

मैंने मावेन डॉक्स को देखा , हालांकि मैं इस कथन को नहीं समझ सकता:

"यह प्लगइन एक uber-jar में विरूपण साक्ष्य को पैकेज करने की क्षमता प्रदान करता है, जिसमें इसकी निर्भरता और छाया भी शामिल है - यानी नाम बदलें - कुछ निर्भरता के पैकेज।"

पृष्ठ पर प्रलेखन बहुत नौसिखिया के अनुकूल नहीं लगता है।

एक "उबर जार क्या है?" कोई एक क्यों बनाना चाहेगा? निर्भरता के पैकेज का नाम बदलने का क्या मतलब है? मैंने मावेन-शेड-प्लगइन एपाचे पेज पर उदाहरणों के माध्यम से जाने की कोशिश की जैसे कि "उबर जार के लिए सामग्री का चयन करना", लेकिन मैं अभी भी समझ नहीं पा रहा हूं कि "छायांकन" के साथ क्या पूरा किया जा रहा है।

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


16
"Uber जार" के नामकरण के लिए, मेरा जर्मन के साथ एकमात्र संबंध है, जहां "über" का अर्थ "ओवर" है। एक साथ शाब्दिक अर्थ है "जार-ओवर-ऑल-अन्य-जार"। "शेडिंग" "पैकेज रियललोकेशन" के रूप में ही है जो कि वर्ग या संसाधनों के लिए आवश्यक है जो टकराते हैं।
dma_k

1
s/reallocation/relocation/उपरोक्त टिप्पणी में।
क्रिस्टोफर

12
यूबर जार एक अंगूठी की तरह है: एक जार उन सभी पर शासन करने के लिए, एक जार उन्हें खोजने के लिए, एक जार उन सभी को लाने के लिए और अंधेरे में उन्हें बांधता है।
मार्टी नितो

जवाबों:


342

Uber JAR, संक्षेप में, एक JAR है जिसमें सब कुछ शामिल है।

सामान्य तौर पर मावेन में, हम निर्भरता प्रबंधन पर भरोसा करते हैं। एक कलाकृति में केवल स्वयं के वर्ग / संसाधन होते हैं। मावेन सभी कलाकृतियों (जेएआर आदि) का पता लगाने के लिए जिम्मेदार होगा कि परियोजना का निर्माण कब किया गया है, इसके आधार पर।

एक uber-jar ऐसी चीज है जो सभी निर्भरता को लेती है, और निर्भरता की सामग्री को निकालती है और उन्हें एक बड़े JAR में प्रोजेक्ट के वर्ग / संसाधनों के साथ डालती है। ऐसे uber-jar होने से, निष्पादन के लिए यह आसान है, क्योंकि आपको अपने ऐप को चलाने के लिए छोटे JAR के टन के बजाय केवल एक बड़े JAR की आवश्यकता होगी। यह कुछ मामलों में वितरण को भी आसान बनाता है।

बस एक साइड-नोट। ओवेन-जार को मावेन निर्भरता के रूप में उपयोग करने से बचें, क्योंकि यह मावेन की निर्भरता संकल्प सुविधा को बर्बाद कर रहा है। आम तौर पर हम केवल वास्तविक तैनाती या मैनुअल वितरण के लिए अंतिम विरूपण साक्ष्य के लिए uber-jar बनाते हैं, लेकिन मावेन रिपॉजिटरी में डालने के लिए नहीं।


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

तैनाती की आसानी के लिए uber-jar बनाना शेड प्लगइन का एक उपयोग मामला है। अन्य सामान्य उपयोग के मामले भी हैं जिनमें पैकेज का नाम बदलना शामिल है।

उदाहरण के लिए, मैं Fooपुस्तकालय विकसित कर रहा हूं , जो पुस्तकालय के एक विशिष्ट संस्करण (उदाहरण 1.0) पर निर्भर करता है Bar। यह मानते हुए कि मैं अन्य संस्करण का उपयोग नहीं कर सकता Bar(क्योंकि एपीआई परिवर्तन, या अन्य तकनीकी मुद्दे, आदि)। अगर मैं मावेन में बस निर्भरता की घोषणा Bar:1.0करता हूं Foo, तो एक समस्या में गिरना संभव है: एक Quxपरियोजना पर निर्भर है Foo, और यह भी Bar:2.0(और यह उपयोग नहीं कर सकता Bar:1.0क्योंकि Quxनई सुविधा का उपयोग करने की आवश्यकता है Bar:2.0)। यहाँ दुविधा है: (जो कोड काम नहीं करेगा) का Quxउपयोग करना चाहिए या (जो कोड काम नहीं करेगा)?Bar:1.0QuxBar:2.0Foo

इस समस्या को हल करने के लिए, डेवलपर Fooइसके उपयोग का नाम बदलने के लिए शेड प्लगइन का उपयोग कर सकता है Bar, ताकि Bar:1.0जार में सभी कक्षाएं जार में एम्बेडेड हों Foo, और एम्बेडेड Barकक्षाओं के पैकेज को इसमें से बदल दिया com.barजाए com.foo.bar। ऐसा करने से, Quxसुरक्षित रूप से निर्भर हो सकता है Bar:2.0क्योंकि अब Fooनिर्भर नहीं है Bar, और इसका उपयोग Barदूसरे पैकेज में स्थित "परिवर्तित" की अपनी प्रति है ।


5
धन्यवाद, जो बहुत मदद करता है। क्या इसे "छायांकन" कहा जाता है क्योंकि यह uber-jar के अंदर निर्भरता और अन्य जार को छुपाता है?
नोव

6
मैं वास्तव में नाम के पीछे के कारण के बारे में निश्चित नहीं हूं, लेकिन इसके फ्रंट पेज से ऐसा लगता है कि "छायांकन" निर्भरता के "छिपाने" का वर्णन कर रहा है। जैसा कि आप वैकल्पिक रूप से छायांकित JAR में कुछ निर्भरता शामिल कर सकते हैं, छाया प्लगइन आपके लिए एक सही POM भी उत्पन्न करेगा जो सम्मिलित निर्भरता को हटाता है। ऐसा लगता है कि छायांकन इस प्रक्रिया का वर्णन कर रहा है
एड्रियन शुम

1
@ एड्रियनशम: क्या आप सुझाव दे सकते हैं कि एक uber जार कैसे बनाएं, बिना शेड प्लगइन का उपयोग किए? या विशेष रूप से "मावेन की निर्भरता संकल्प सुविधा को बर्बाद करने" को कैसे हल किया जाए?
सूरज मेनन

3
@SurajMenon: uber-jar बनाने के लिए शेड प्लगइन का उपयोग करना सबसे आसान तरीका है। हालाँकि, आप असेंबली प्लगइन का उपयोग भी कर सकते हैं, और अंतर्निहित jar-with-dependencyडिस्क्रिप्टर का उपयोग कर सकते हैं । Uber-jar के उपयोग पर निर्भरता roslution की समस्या के लिए, मैंने पहले ही अपने उत्तर में उल्लेख किया है: uber-jar का उपयोग निर्भरता, अवधि के रूप में न करें। थोड़ा और विस्तार से: उबेर-जार बनाने से पहले, आपके पास सामान्य निर्भरता के साथ एक सामान्य परियोजना होनी चाहिए। वह मूल कलाकृति वह है जिसे आपको निर्भरता (यूबर-जार के बजाय) के रूप में उपयोग करना चाहिए
एड्रियन शम

1
बस एक मामूली सवाल: क्या यह Class.forNameकाम करने से रोकता है?
SOFe

64

मैं अपने आप को हाल ही में आश्चर्यचकित कर रहा था कि एलेस्टिक्स खोज क्यों और निर्भरता के कुछ (लेकिन सभी नहीं) को स्थानांतरित करता है। यहाँ परियोजना के अनुचर से एक स्पष्टीकरण है, @kimchy :

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

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

- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766

और दूसरा यहाँ से ड्रूवर :

छायांकन हमारे कोड के पास हमारी निर्भरता (विशेष रूप से कुलीनता, ल्यूसीन, अमरूद) को बनाए रखने के लिए महत्वपूर्ण है ताकि हम एक समस्या को ठीक कर सकें, भले ही अपस्ट्रीम प्रदाता पीछे रह जाए। यह संभव है कि हम कोड के मॉड्यूलर संस्करण वितरित करेंगे, जो आपके विशेष अंक (उदाहरण के लिए # 2091) के साथ मदद करेगा, लेकिन हम इस समय केवल छायांकित निर्भरता को नहीं निकाल सकते। आप अपने उद्देश्यों के लिए ES का एक स्थानीय संस्करण बना सकते हैं जब तक कि एक बेहतर समाधान न हो।

- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125252

तो, यह एक उपयोग मामला है। उदाहरण के लिए, नीचे इलास्टिक खोज के pom.xml (v0.90.5) में मावेन-शेड-प्लगइन का उपयोग किस प्रकार किया गया है। artifactSet::includeलाइनों यह हिदायत क्या uber जार (मूल रूप से, वे अनज़िप कर रहे हैं और और elasticsearch की अपनी कक्षाओं के साथ फिर से पैक किया जब लक्ष्य elasticsearch जार का उत्पादन किया है। (मामले में आप यह पहले से ही पता नहीं था में खींचने के लिए निर्भरता, एक जार फ़ाइल है सिर्फ एक ज़िप फ़ाइल जिसमें प्रोग्राम की कक्षाएं, संसाधन, आदि और कुछ मेटाडेटा शामिल हैं। आप यह देखने के लिए एक निकाल सकते हैं कि यह एक साथ कैसे है।)

relocations::relocationइस मामले में उनके अधीन लाने - लाइनों, सिवाय इसके कि प्रत्येक मामले में वे भी निर्दिष्ट प्रतिस्थापन निर्भरता के वर्गों के लिए लागू होते हैं, इसी तरह के हैं org.elasticsearch.common

अंत में filtersअनुभाग लक्ष्य JAR से कुछ सामान को बाहर कर देता है जो इसमें नहीं होना चाहिए - जैसे कि JAR मेटाडेटा, चींटी बिल्ड फाइलें, पाठ फ़ाइलें आदि, जो कुछ निर्भरता के साथ पैक किए जाते हैं, लेकिन जो एक uber JAR से संबंधित नहीं हैं।

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.1</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <minimizeJar>true</minimizeJar>
            <artifactSet>
                <includes>
                    <include>com.google.guava:guava</include>
                    <include>net.sf.trove4j:trove4j</include>
                    <include>org.mvel:mvel2</include>
                    <include>com.fasterxml.jackson.core:jackson-core</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
                    <include>joda-time:joda-time</include>
                    <include>io.netty:netty</include>
                    <include>com.ning:compress-lzf</include>
                </includes>
            </artifactSet>
            <relocations>
                <relocation>
                    <pattern>com.google.common</pattern>
                    <shadedPattern>org.elasticsearch.common</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>gnu.trove</pattern>
                    <shadedPattern>org.elasticsearch.common.trove</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166y</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166e</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.mvel2</pattern>
                    <shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.fasterxml.jackson</pattern>
                    <shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.joda</pattern>
                    <shadedPattern>org.elasticsearch.common.joda</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.jboss.netty</pattern>
                    <shadedPattern>org.elasticsearch.common.netty</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.ning.compress</pattern>
                    <shadedPattern>org.elasticsearch.common.compress</shadedPattern>
                </relocation>
            </relocations>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/license/**</exclude>
                        <exclude>META-INF/*</exclude>
                        <exclude>META-INF/maven/**</exclude>
                        <exclude>LICENSE</exclude>
                        <exclude>NOTICE</exclude>
                        <exclude>/*.txt</exclude>
                        <exclude>build.properties</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
    </plugin>
</plugins>

2

छोटी चेतावनी

हालाँकि यह वर्णित नहीं है कि मावेन-शेड-प्लगइन का उपयोग क्यों करना चाहते हैं (चूंकि चयनित उत्तर इसे बहुत अच्छी तरह से वर्णित करता है), मैं यह नोट करना चाहूंगा कि मुझे इसके साथ समस्या थी। इसने JAR को बदल दिया (क्योंकि यह क्या कर रहा है) और इसने मेरे सॉफ्टवेयर में प्रतिगमन पैदा कर दिया।

इसलिए, इस (या मावेन-जारजार-प्लगइन) का उपयोग करने के बजाय, मैंने जारजार के बाइनरी का उपयोग किया है जो बिना किसी समस्या के काम करता है।

मैं अपना समाधान यहाँ पोस्ट कर रहा हूँ क्योंकि मुझे एक अच्छा समाधान खोजने में कुछ समय लगा।


डाउनलॉड जारजार की जार फ़ाइल

आप यहां से जार डाउनलोड कर सकते हैं: https://code.google.com/p/jarjar/ बाएं मेनू में आपको इसे डाउनलोड करने के लिए एक लिंक मिला है।


जार के वर्गों को एक पैकेज से दूसरे पैकेज में स्थानांतरित करने के लिए जारजार का उपयोग कैसे करें

इस उदाहरण में हम "com.fasterxml.jackson" से पैकेज को "io.kuku.dependencies.com.fasterxml.jackson" में बदल देंगे। - स्रोत JAR को "जैकसन-डेटाबाइंड-2.6.4.jar" और नए संशोधित (लक्ष्य) JAR को "कुकू-जैकसन-डेटाबाइंड-2.6.4.jar" कहा जाता है। - "जारजार" जार फ़ाइल 1.4 संस्करण में है

  1. एक "rules.txt" फ़ाइल बनाएँ। फ़ाइल की सामग्री होनी चाहिए ('@' वर्ण से पहले की अवधि देखें): नियम com.fasterxml.jackson। ** io.kuku.dependencies.com.fasterxml.jackson। @ 1

  2. निम्न आदेश चलाएँ: java-jar jarjar-1.4.jar प्रक्रिया के नियम। txt जैक्सन-डेटाबाइंड-2.6.4.jar kuku-jackson-databind-2.6.4.jar


स्थानीय भंडार में संशोधित JARs स्थापित करना

इस स्थिति में मैं "c: \ my-jars \" फ़ोल्डर पर स्थित 3 फाइलें स्थापित कर रहा हूं।

mvn इंस्टॉल: इंस्टॉल-फाइल -Dfile = C: \ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.d dependencies -DartifactId = टुक-जैकसन-एनोटेशन -Dversion = 2.6.4 - Dpackaging = जार

mvan install: install-file -Dfile = C: \ my-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4 - Dpackaging = जार

mvan install: install-file -Dfile = C: \ my-jars \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = टुक-जैकसन-एनोटेशन -Dversion = 2.6.4 - Dpackaging = जार


प्रोजेक्ट के पोम में संशोधित JAR का उपयोग करना

इस उदाहरण में, यह परियोजनाओं में "निर्भरता" तत्व है पोम:

<dependencies>
    <!-- ================================================== -->
    <!-- kuku JARs -->
    <!-- ================================================== -->
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-annotations</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-core</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-databind</artifactId>
        <version>2.6.4</version>
    </dependency>
</dependencies>

1
इस वैकल्पिक सुझाव के लिए धन्यवाद। यह वह नहीं था जिसकी मैं तलाश कर रहा था बल्कि विरासत पुस्तकालयों पर 1-बार पैकेज अनुवाद लागू करने के लिए बहुत सरल और तेज समाधान निकला जो कभी नहीं बदलेगा।
फ्रीलांसिंग

क्या आपने उनके संबंधित आउटपुट की सामग्री की तुलना करके ऐसी विफलताओं का कारण पता लगाया है?
आदिवासी

2

मुझे लगता है कि "छायांकित" जार की आवश्यकता का एक उदाहरण एक एडब्ल्यूएस लाम्बा फ़ंक्शन है। वे आपको केवल 1 जार अपलोड करने देते हैं, न कि संपूर्ण .jars जैसे कि आप एक विशिष्ट .war फ़ाइल में पाएंगे। तो, परियोजना के सभी निर्भरता के साथ एक एकल .jar बनाना आपको ऐसा करने की अनुमति देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.