संकलित समय बनाम रन समय निर्भरता - जावा


91

जावा में संकलित समय और रन समय निर्भरता के बीच अंतर क्या है? यह वर्ग पथ से संबंधित है, लेकिन वे कैसे भिन्न हैं?

जवाबों:


78
  • संकलन-समय निर्भरता : आपको CLASSPATHअपनी कलाकृतियों को संकलित करने के लिए निर्भरता की आवश्यकता है। वे उत्पादित होते हैं क्योंकि आपके पास कोड में किसी प्रकार की निर्भरता हार्डकोड करने के लिए "संदर्भ" होता है, जैसे कि newकुछ वर्ग के लिए कॉल करना , किसी चीज़ का विस्तार करना या लागू करना (या तो प्रत्यक्ष या अप्रत्यक्ष रूप से), या डायरेक्ट reference.method()नोटेशन का उपयोग करके एक विधि कॉल ।

  • रन-टाइम निर्भरता : CLASSPATHअपनी कलाकृतियों को चलाने के लिए आपको अपनी निर्भरता की आवश्यकता होती है। वे उत्पादित होते हैं क्योंकि आप कोड को निष्पादित करते हैं जो निर्भरता तक पहुंचता है (या तो हार्डकोड तरीके से या प्रतिबिंब के माध्यम से या जो भी)।

यद्यपि संकलन-समय निर्भरता आमतौर पर रन-टाइम निर्भरता का अर्थ है, आपके पास केवल संकलन-समय निर्भरता हो सकती है। यह इस तथ्य पर आधारित है कि जावा केवल उस वर्ग तक पहली पहुंच पर वर्ग निर्भरता को जोड़ता है, इसलिए यदि आप रन-टाइम पर किसी विशेष वर्ग तक कभी नहीं पहुंचते हैं क्योंकि एक कोड पथ कभी नहीं निकाला जाता है, तो जावा वर्ग और उसकी निर्भरता दोनों को अनदेखा करेगा।

इसका उदाहरण है

C.java में (C.class उत्पन्न करता है):

package dependencies;
public class C { }

अजावा में (ए। अकास उत्पन्न करता है):

package dependencies;
public class A {
    public static class B {
        public String toString() {
            C c = new C();
            return c.toString();
        }
    }
    public static void main(String[] args) {
        if (args.length > 0) {
            B b = new B();
            System.out.println(b.toString());
        }
    }
}

इस मामले में, के माध्यम से Aएक संकलन-समय पर निर्भरता है , लेकिन यह केवल C पर एक रन-टाइम निर्भरता है यदि आप निष्पादित करते समय कुछ पैरामीटर पास करते हैं , क्योंकि JVM केवल निष्पादित होने पर निर्भरता को हल करने का प्रयास करेगा। । यह सुविधा आपको रनटाइम पर केवल उन वर्गों की निर्भरता प्रदान करने की अनुमति देती है जो आप अपने कोड पथों में उपयोग करते हैं, और कलाकृतियों में बाकी कक्षाओं की निर्भरता को अनदेखा करते हैं।CBjava dependencies.ABCB b = new B()


1
मुझे पता है कि यह अब बहुत पुराना जवाब है, लेकिन जेवीएम के पास शुरू से ही रनटाइम निर्भरता के रूप में सी कैसे नहीं हो सकता है? यदि यह "यहाँ सी के संदर्भ, समय को एक निर्भरता के रूप में जोड़ने के लिए" को पहचानने में सक्षम है, तो सी पहले से अनिवार्य रूप से नहीं है क्योंकि जेवीएम इसे पहचानता है और जानता है कि यह कहां है?
वेयरबोब

@wearebob यह निर्दिष्ट किया जा सकता है कि मैं जिस तरह से अनुमान लगा रहा हूं, लेकिन उन्होंने फैसला किया कि आलसी लिंकिंग बेहतर था, और व्यक्तिगत रूप से मैं ऊपर बताए गए कारण से सहमत हूं: यह आपको आवश्यक होने पर कुछ कोड का उपयोग करने की अनुमति देता है, लेकिन आपको इसे इसमें शामिल करने के लिए मजबूर नहीं करता है। यदि आपको इसकी आवश्यकता नहीं है तो आपकी तैनाती। थर्ड पार्टी कोड से निपटने के दौरान यह काफी आसान है।
gpeche

अगर मैं एक जार कहीं तैनात है, हालांकि, यह पहले से ही यह निर्भरता के सभी को शामिल करने जा रहा है। यह नहीं पता है कि यह तर्कों के साथ चलाया जाएगा या नहीं (इसलिए यह नहीं पता है कि सी का उपयोग किया जाएगा या नहीं), इसलिए इसे सी या तो उपलब्ध होना होगा। मैं अभी यह नहीं देखता कि प्रारंभ से क्लासपाथ पर सी नहीं होने से कोई भी मेमोरी / समय कैसे बचाया जाता है।
बुनरीबोब

1
@wearebob a JAR को अपनी सभी निर्भरताओं को शामिल करने की आवश्यकता नहीं है। यही कारण है कि लगभग हर गैर-तुच्छ एप्लिकेशन के पास / lib निर्देशिका या एकाधिक JAR वाले समान हैं।
19ec पर gpeche

33

एक आसान उदाहरण सर्वलेट एपी की तरह एक एपी को देखना है। अपने सर्वलेट्स को संकलित करने के लिए, आपको सर्वलेट-एपी.जर की आवश्यकता है, लेकिन रनटाइम के दौरान सर्वलेट कंटेनर एक सर्वलेट एपि कार्यान्वयन प्रदान करता है, इसलिए आपको अपने रनटाइम क्लास पथ में सर्वलेट-एपी.जर जोड़ने की आवश्यकता नहीं है।


स्पष्टीकरण के लिए (यह मुझे भ्रमित करता है), यदि आप मावेन का उपयोग कर रहे हैं और एक युद्ध का निर्माण कर रहे हैं, तो "सर्वलेट-एपी" आमतौर पर "रनटाइम" निर्भरता के बजाय एक "प्रदान" निर्भरता है, जिसके कारण इसे युद्ध में शामिल किया जाएगा, यदि मैं सही हूँ।
xdhmoore

2
'प्रदान' का अर्थ है, संकलन समय पर शामिल करें, लेकिन इसे WAR या निर्भरता के अन्य संग्रह में बंडल न करें। 'रनटाइम' विपरीत करता है (संकलन पर उपलब्ध नहीं है, लेकिन WAR के साथ पैक किया गया है)।
केसी बाल्ट्ज

29

संकलक को लाइब्रेरी में कॉल संकलित करने के लिए सही क्लासपाथ की आवश्यकता होती है (संकलन समय निर्भरता)

जिस लाइब्रेरी को आप कॉल कर रहे हैं (रनटाइम डिपेंडेंसी), उस क्लास में लोड करने के लिए जेवीएम को सही क्लासपैथ की जरूरत होती है।

वे कुछ तरीकों से भिन्न हो सकते हैं:

1) अगर आपकी क्लास C1 लाइब्रेरी क्लास L1 कहती है, और L1 लाइब्रेरी क्लास L2 कहती है, तो C1 में L1 और L2 पर रनटाइम डिपेंडेंसी है, लेकिन L1 पर केवल एक संकलन समय निर्भरता है।

2) यदि आपकी कक्षा C1 डायनामिक रूप से I1 को Class.forName () या कुछ अन्य तंत्र का उपयोग करती है, और इंटरफ़ेस I1 के लिए कार्यान्वयन वर्ग क्लास L1 है, तो C1 में I1 और L1 पर रनटाइम निर्भरता है, लेकिन केवल एक संकलन समय निर्भरता है। I1 पर।

अन्य "अप्रत्यक्ष" निर्भरताएं जो संकलन-समय और रन-टाइम के लिए समान हैं:

3) आपकी क्लास C1 लाइब्रेरी क्लास L1 तक फैली हुई है, और L1 इम्प्रूवमेंट इंटरफ़ेस I1 का विस्तार करती है और लाइब्रेरी क्लास L2 का विस्तार करती है: C1 में L1, L2 और I1 पर एक कंपाइल-टाइम डिपेंडेंसी है।

4) आपके वर्ग C1 में एक विधि foo(I1 i1)और एक विधि है bar(L1 l1)जहाँ I1 एक इंटरफ़ेस है और L1 एक वर्ग है जो एक पैरामीटर लेता है जो इंटरफ़ेस I1 है: C1 में I1 और L1 पर एक संकलन-समय निर्भरता है।

मूल रूप से, कुछ भी दिलचस्प करने के लिए, आपकी कक्षा को अन्य कक्षाओं और इंटरफ़ेस के साथ क्लासपैथ में इंटरफ़ेस करने की आवश्यकता होती है। लाइब्रेरी इंटरफेस के उस सेट द्वारा गठित क्लास / इंटरफ़ेस ग्राफ , संकलन-समय निर्भरता श्रृंखला की उपज देता है। पुस्तकालय कार्यान्वयन रन-टाइम निर्भरता श्रृंखला उपजते हैं। ध्यान दें कि रन-टाइम डिपेंडेंसी चेन रन-टाइम डिपेंडेंट या फेल-स्लो है: यदि L1 का कार्यान्वयन कभी-कभी क्लास L2 के ऑब्जेक्ट को इंस्टेंटिमिट करने पर निर्भर करता है, और वह क्लास केवल एक विशेष परिदृश्य में तुरंत हो जाती है, तो इसके अलावा कोई भरोसेमंद संभावना नहीं है वह परिदृश्य।


1
उदाहरण 1 में अनिवार्य निर्भरता नहीं होना चाहिए L1?
बालुसक

धन्यवाद, लेकिन रन टाइम में क्लास लोडिंग कैसे काम करती है? संकलन के समय यह समझना आसान है। लेकिन रनटाइम में, यह कैसे कार्य करता है, एक मामले में जब मेरे पास विभिन्न संस्करणों के दो जार हैं? इसे कौन सा उठाएगा?
कुणाल

1
मुझे पूरा यकीन है कि डिफॉल्ट क्लास लोडर क्लासपाथ लेता है और क्रम में इसके माध्यम से कदम बढ़ाता है, इसलिए यदि आपके पास क्लासपैथ में दो जार हैं कि दोनों में एक ही क्लास शामिल है (जैसे com.example.fooutils.Foo), तो यह एक का उपयोग करेगा पहली कक्षा में है। या तो आपको अस्पष्टता बताते हुए कोई त्रुटि मिलेगी। लेकिन यदि आप क्लास लोडर के लिए अधिक विशिष्ट जानकारी चाहते हैं तो आपको एक अलग प्रश्न पूछना चाहिए।
जेसन एस

मुझे लगता है कि पहले मामले में, संकलन समय निर्भरताएँ L2 पर भी होनी चाहिए अर्थात वाक्य इस प्रकार होना चाहिए: 1) यदि आपकी कक्षा C1 को लाइब्रेरी क्लास L1 कहती है, और L1 लाइब्रेरी क्लास L2 को कॉल करती है, तो C1 में L1 और L2, लेकिन L1 & L2 पर केवल एक संकलन समय निर्भरता। यह ऐसा है, जैसा कि संकलन के समय में भी जब जावा कंपाइलर L1 की पुष्टि करता है, तो यह L1 द्वारा संदर्भित अन्य सभी वर्गों (Class.forName ("myclassname) जैसी गतिशील निर्भरता को छोड़कर) को भी सत्यापित करता है। अन्यथा यह कैसे सत्यापित करता है" संकलन ठीक काम कर रहा है। यदि आप अन्यथा सोचते हैं तो कृपया बताएं
राजेश गोयल

1
नहीं, आपको यह पढ़ने की आवश्यकता है कि जावा में संकलन और लिंकेज कैसे काम करता है। सभी संकलक के बारे में परवाह है, जब यह एक बाहरी वर्ग को संदर्भित करता है, तो उस वर्ग का उपयोग कैसे किया जाता है , जैसे कि इसके तरीके और क्षेत्र क्या हैं। यह परवाह नहीं करता कि वास्तव में उस बाहरी वर्ग के तरीकों में क्या होता है। यदि L1 L2 कहता है, तो यह L1 का कार्यान्वयन विवरण है, और L1 को पहले ही कहीं और संकलित किया गया है।
जेसन एस

12

जावा वास्तव में संकलन समय पर कुछ भी लिंक नहीं करता है। यह केवल उन मिलान वर्गों का उपयोग करके सिंटैक्स की पुष्टि करता है जो इसे CLASSPATH में पाता है। यह रनटाइम तक नहीं है कि सब कुछ एक साथ रखा जाता है और उस समय CLASSPATH के आधार पर निष्पादित होता है।


इसकी लोडिंग तक नहीं ... रनटाइम लोडटाइम से अलग है।
ओवरएक्सचेंज

10

कंपाइलटाइम निर्भरता केवल निर्भरता (अन्य कक्षाएं) हैं जो आप उस कक्षा में सीधे उपयोग करते हैं जिसे आप संकलित कर रहे हैं। रनटाइम निर्भरताएँ आपके द्वारा चलाए जा रहे वर्ग की प्रत्यक्ष और अप्रत्यक्ष निर्भरता दोनों को कवर करती हैं। इस प्रकार, रनटाइम निर्भरता में निर्भरता की निर्भरता और किसी भी प्रतिबिंब पर निर्भरता जैसे क्लासनाम शामिल हैं जो आपके पास है String, लेकिन इसमें उपयोग किया जाता है Class#forName()


धन्यवाद, लेकिन रन टाइम में क्लास लोडिंग कैसे काम करती है? संकलन के समय यह समझना आसान है। लेकिन रनटाइम में, यह कैसे कार्य करता है, एक मामले में जब मेरे पास विभिन्न संस्करणों के दो जार हैं? एक वर्ग पथ में विभिन्न वर्गों के कई वर्गों के मामले में कौन सा वर्ग Class.forName () पिकअप होगा?
कुणाल

पाठ्यक्रम के नाम से मेल खाने वाला। यदि आप वास्तव में "एक ही कक्षा के कई संस्करण" का अर्थ करते हैं, तो यह क्लास लोडर पर निर्भर करता है। "निकटतम" एक लोड किया जाएगा।
बालुस सी सी

वैसे मुझे लगता है कि अगर आपके पास A.jar है A, B.jar with B extends Aऔर C.jar है C extends Bतो C.jar का संकलन समय पर निर्भर करता है, जबकि A पर C निर्भरता अप्रत्यक्ष है।
gpeche

1
सभी संकलन-समय पर निर्भरता में समस्या इंटरफ़ेस निर्भरता है (चाहे इंटरफ़ेस एक वर्ग के तरीकों के माध्यम से हो, या एक इंटरफ़ेस के तरीकों के माध्यम से, या एक विधि के माध्यम से जिसमें एक तर्क होता है जो एक वर्ग या इंटरफ़ेस है)
जेसन एस

2

जावा के लिए, संकलन समय निर्भरता आपके स्रोत कोड की निर्भरता है। उदाहरण के लिए, यदि वर्ग A वर्ग B से एक विधि कहता है, तो A, संकलन समय पर B पर निर्भर है क्योंकि A को B के प्रकार (B के प्रकार) के बारे में जानना है। यहाँ चाल यह होनी चाहिए: संकलित कोड अभी तक एक पूर्ण और निष्पादन योग्य कोड नहीं है। इसमें उन स्रोतों के लिए बदली पते (प्रतीक, मेटाडेटा) शामिल हैं, जो अभी तक बाहरी जार में संकलित या विद्यमान नहीं हैं। लिंक करने के दौरान, उन पतों को स्मृति में वास्तविक एड्रेसेस द्वारा प्रतिस्थापित किया जाना चाहिए। इसे ठीक से करने के लिए, सही प्रतीकों / आदतों का निर्माण किया जाना चाहिए। और यह वर्ग (बी) के प्रकार के साथ किया जा सकता है। मेरा मानना ​​है कि संकलन के समय मुख्य निर्भरता है।

रनटाइम निर्भरता वास्तविक प्रवाह-नियंत्रण से अधिक संबंधित है। यह वास्तविक मेमोरी पतों पर आक्रमण करता है। यह एक निर्भरता है जो आपके पास है जब आपका कार्यक्रम चल रहा है। आपको यहां क्लास बी विवरण की आवश्यकता है जैसे कि कार्यान्वयन, न केवल प्रकार की जानकारी। यदि वर्ग मौजूद नहीं है, तो आपको RuntimeException मिल जाएगी और JVM बाहर निकल जाएगा।

दोनों निर्भरता, आम तौर पर और एक ही दिशा में प्रवाह नहीं होना चाहिए। यह हालांकि OO डिजाइन का मामला है।

C ++ में, संकलन थोड़ा अलग है (सिर्फ-इन-टाइम नहीं), लेकिन इसमें एक लिंकर भी है। तो इस प्रक्रिया को जावा I अनुमान के समान माना जा सकता है।

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