वंशानुक्रम: क्या सुपरक्लास से कोड वस्तुतः * कॉपी किया गया * उप-वर्ग के लिए है, या क्या यह * उप-द्वारा * संदर्भित है?


10

क्लास क्लास Subका एक उपवर्ग है Sup। व्यावहारिक रूप से इसका क्या मतलब है? या दूसरे शब्दों में, "विरासत" का व्यावहारिक अर्थ क्या है?

विकल्प 1: सुपर से कोड वस्तुतः उप की नकल है। (जैसा कि 'कॉपी-पेस्ट' में है, लेकिन कॉपी किए गए कोड के बिना नेत्रहीन उपवर्ग में दिखाई देता है)।

उदाहरण: methodA()सुपर में मूल रूप से एक विधि है। सब, सुपर को बढ़ाता है, इसलिए methodA()(वस्तुतः) सब को कॉपी-पेस्ट किया जाता है। अब सब के पास एक विधि है जिसका नाम है methodA()यह methodA()कोड की प्रत्येक पंक्ति में Sup के समान है , लेकिन पूरी तरह से Sub से संबंधित है - और Sup पर निर्भर नहीं करता है या किसी भी तरह से Sup से संबंधित है।

विकल्प 2: सुपर से कोड वास्तव में उप की नकल नहीं है । यह अभी भी केवल सुपरक्लास में है। लेकिन उस कोड को उपवर्ग के माध्यम से पहुँचा जा सकता है और उपवर्ग द्वारा उपयोग किया जा सकता है।

उदाहरण: methodA()सुपर में एक विधि है। उप का विस्तार होता है, इसलिए अब methodA()उप के माध्यम से पहुँचा जा सकता है जैसे subInstance.methodA():। लेकिन वह वास्तव में सुपरक्लास methodA()में शामिल होगा । जिसका अर्थ है कि मेथड () सुपरक्लास के संदर्भ में संचालित होगा, भले ही इसे उपवर्ग द्वारा बुलाया गया हो।

प्रश्न: वास्तव में दो विकल्पों में से कौन सा काम करता है? यदि उनमें से कोई भी नहीं है, तो कृपया बताएं कि ये चीजें वास्तव में कैसे काम करती हैं।


यह खुद के लिए परीक्षण करना आसान है - कोड लिखें, वर्ग फ़ाइलों की जांच करें (यहां तक ​​कि एक चेकसम यह भी करेगा), सुपर क्लास को संशोधित करें, फिर से संकलित करें, फिर से वर्ग फ़ाइलों को देखें। आप पढ़ने के अध्याय 3 भी पा सकते हैं । जेवीएम विनिर्देश के जावा वर्चुअल मशीन को समझने में मदद करने के लिए संकलन (विशेषकर खंड 3.7)।

@MichaelT " वस्तुतः कॉपी किया गया" कीवर्ड है। इसके अलावा, यहां तक ​​कि अगर कोड को सचमुच कॉपी किया जा रहा था, तो यह केवल क्लास लोडिंग के बाद हो सकता है।

@delnan यह उत्सुक होगा यदि हॉटस्पॉट (या अन्य रनटाइम ऑप्टिमाइज़र) किसी बिंदु पर कोड को इनलाइन करेगा, लेकिन यह JVM का कार्यान्वयन विवरण बन जाता है जो एक JVM से दूसरे में भिन्न हो सकता है और इसलिए इसका सही उत्तर नहीं दिया जा सकता है। सबसे अच्छा जो किया जा सकता है वह संकलित बायटेकोड (और वास्तव में जो कुछ भी होता है उसका वर्णन करता है) का उपयोग कर रहा है

जवाबों:


13

विकल्प 2।

बाइटकोड को रनटाइम पर गतिशील रूप से संदर्भित किया जाता है: यही कारण है कि, उदाहरण के लिए, लिंकेजर्स होते हैं।

उदाहरण के लिए, मान लें कि आप दो वर्गों को संकलित करते हैं:

public class Parent {
  public void doSomething(String x) { ... }
}

public class Child extends Parent {
  @Override
  public void doSomething(String x) {
    super.doSomething(x);
    ...
  }
}

अब बच्चे वर्ग को संशोधित या पुन : व्यवस्थित किए बिना मूल वर्ग को संशोधित और पुन : व्यवस्थित करें :

public class Parent {
  public void doSomething(Collection<?> x) { ... }
}

अंत में, एक प्रोग्राम चलाएं जो चाइल्ड क्लास का उपयोग करता है। आपको एक NoSuchMethodError प्राप्त होगी :

यदि कोई एप्लिकेशन वर्ग (या तो स्थिर या उदाहरण) की एक निर्दिष्ट पद्धति को कॉल करने का प्रयास करता है, और उस वर्ग की अब उस पद्धति की परिभाषा नहीं है।

आम तौर पर, यह त्रुटि संकलक द्वारा पकड़ी जाती है; यह त्रुटि केवल रन टाइम पर हो सकती है यदि किसी वर्ग की परिभाषा असंगत रूप से बदल गई हो।


7

दो सरल वर्गों के साथ शुरू करते हैं:

package com.michaelt.so.supers;

public class Sup {
    int methodA(int a, int b) {
        return a + b;
    }
}

और फिर

package com.michaelt.so.supers;

public class Sub extends Sup {
    @Override
    int methodA(int a, int b) {
        return super.methodA(a, b);
    }
}

कम्पाइलिंग मेथड और बाइट कोड को देखते हुए एक हो जाता है:

  methodA(II)I
   L0
    LINENUMBER 6 L0
    ALOAD 0
    ILOAD 1
    ILOAD 2
    INVOKESPECIAL com/michaelt/so/supers/Sup.methodA (II)I
    IRETURN
   L1
    LOCALVARIABLE this Lcom/michaelt/so/supers/Sub; L0 L1 0
    LOCALVARIABLE a I L0 L1 1
    LOCALVARIABLE b I L0 L1 2
    MAXSTACK = 3
    MAXLOCALS = 3

और आप वहीं देख सकते हैं जो कि इनकॉस्पेक्टिव विधि के साथ यह सुपर क्लास मेथड () के खिलाफ लुकअप करता है।

Invokespecial opcode निम्नलिखित तर्क है:

  • यदि C में एक ही नाम और वर्णनात्मक विधि के साथ एक उदाहरण विधि के लिए एक घोषणा शामिल है, तो यह विधि लागू होगी। लुकअप प्रक्रिया समाप्त हो जाती है।
  • अन्यथा, यदि C का सुपरक्लास है, तो इसी लुकअप प्रक्रिया को सी के प्रत्यक्ष सुपरक्लास का उपयोग करके पुन: प्रदर्शित किया जाता है। जिस विधि को लागू किया जाना है वह इस लुकअप प्रक्रिया के पुनरावर्ती मंगलाचरण का परिणाम है।
  • अन्यथा, एक AbstractMethodError उठाया जाता है।

इस मामले में, एक ही नाम और विवरणकर्ता के साथ कोई उदाहरण विधि नहीं है ताकि उसकी कक्षा में पहली गोली चल सके। हालांकि दूसरी गोली - एक सुपरक्लास होगी और यह सुपर के तरीके का आह्वान करती है।

कंपाइलर इनलाइन नहीं करता है और वर्ग में सुपर के स्रोत की कोई प्रतिलिपि नहीं है।

हालाँकि कहानी अभी खत्म नहीं हुई है। यह सिर्फ संकलित कोड है। कोड JVM हिट होने के बाद, हॉटस्पॉट शामिल हो सकता है।

दुर्भाग्य से, मैं इसके बारे में है कि ज्यादा पता नहीं है, इसलिए मैं इस मामले पर अधिकार के लिए अपील और के लिए जाना जाएगा जावा में इनलाइन किए जहां यह कहा जाता है कि हॉटस्पॉट कर सकते हैं तरीकों (यहां तक कि गैर अंतिम विधि) इनलाइन।

के लिए जा रहे डॉक्स को प्रभावी ढंग से Sup MethodA से कोड (कॉपी करने) उप MethodA में () - यह है कि एक विशेष विधि कॉल के बजाय कर रही है कि हर बार देखने, इस जानकारी को inlined किया जा सकता है की एक गर्म स्थान बन जाता है, तो विख्यात है।

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

जैसा कि OpenJDK के लिए हॉटस्पॉट इंटर्नल्स में कहा गया है "विधियां अक्सर अंतर्निर्मित होती हैं। स्टेटिक, निजी, अंतिम और / या" विशेष "इनवोकेशन आसान इनलाइन हैं।"

यदि आप JVM के लिए विकल्पों में खुदाई करते हैं, तो आपको -XX:MaxInlineSize=35(35 डिफ़ॉल्ट होने का) एक विकल्प मिलेगा जो कि बाइट्स की अधिकतम संख्या है जो कि इनलाइन हो सकती है। मैं बताता हूं कि यही कारण है कि जावा को बहुत कम तरीके पसंद हैं - क्योंकि वे आसानी से इनलेट हो सकते हैं। वे छोटी विधियाँ तब तेज हो जाती हैं जब उन्हें अधिक कहा जाता है क्योंकि वे अंतर्निर्मित हो सकती हैं। और जबकि कोई उस नंबर के साथ खेल सकता है और इसे बड़ा बना सकता है, इससे अन्य अनुकूलन कम प्रभावी हो सकते हैं। (संबंधित एसओ सवाल: हॉटस्पॉट जेआईएल इनलाइनिंग रणनीति जो कि हॉटस्पॉट कर रहे इनलाइन के आंतरिक पर नज़र रखने के लिए कई अन्य विकल्पों को इंगित करती है)।

तो, नहीं - कोड संकलन समय पर इनबिल्ड नहीं है। और, हां - यदि प्रदर्शन अनुकूलन इसे जारी रखते हैं तो कोड रनटाइम पर बहुत अच्छी तरह से इनलेट हो सकता है।

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


0

कोड की प्रतिलिपि नहीं बनाई गई है, इसे संदर्भ द्वारा एक्सेस किया गया है:

  • उपवर्ग अपने तरीकों और सुपरक्लास का संदर्भ देता है
  • सुपरक्लास अपने तरीकों का संदर्भ देता है

संकलक अनुकूलित कर सकते हैं कि यह कैसे स्मृति में दर्शाया / निष्पादित किया जाता है, लेकिन यह मूल रूप से संरचना है

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