2009-10-01 8 views
56

मैं this article पढ़ रहा हूं कि JVM कैसे विधियों को आमंत्रित करता है, और मुझे लगता है कि मुझे इसमें से अधिकतर मिला है। हालांकि, मुझे अभी भी invokeinterface की आवश्यकता को समझने में परेशानी हो रही है।invokeinterface का मुद्दा क्या है?

जिस तरह से मैं इसे समझता हूं, कक्षा में मूल रूप से विधियों की आभासी तालिका होती है और invokevirtual या invokeinterface के साथ विधि को कॉल करते समय इस वर्चुअल तालिका से परामर्श किया जाता है।

इंटरफ़ेस पर परिभाषित विधि और बेस क्लास पर परिभाषित विधि के बीच क्या अंतर है? विभिन्न बाइटकोड क्यों?

description of the instructions भी बहुत समान दिखता है।

आलेख का दावा है कि एक इंटरफ़ेस की विधि तालिका में प्रत्येक विधि को "अलग ऑफसेट" हो सकता है। जो मुझे समझ में नहीं आता है, क्यों एक इंटरफ़ेस में एक विधि तालिका होगी, क्योंकि किसी ऑब्जेक्ट में इंटरफ़ेस का वास्तविक प्रकार नहीं हो सकता है।

मुझे क्या याद आ रही है?

+3

देखें [जावा इंटरफेस का प्रभावशाली कार्यान्वयन: Invokeinterface माना जाता है] [http://www.research.ibm.com/people/d/dgrove/papers/oopsla01.pdf)। –

+1

इसमें वर्चुअल विधियों की एक तालिका है। तालिका स्वयं वर्चुअल नहीं है;) –

उत्तर

78

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

class BaseClass { 
    public void method1() { } 
    public void method2() { } 
    public void method3() { } 
} 

class NextClass extends BaseClass { 
    public void method2() { } // overridden from BaseClass 
    public void method4() { } 
} 

परिणाम

BaseClass 
1. BaseClass/method1() 
2. BaseClass/method2() 
3. BaseClass/method3() 

NextClass 
1. BaseClass/method1() 
2. NextClass/method2() 
3. BaseClass/method3() 
4. NextClass/method4()

ध्यान दें, कैसे NextClass की आभासी विधि तालिका BaseClass की मेज की प्रविष्टियों के आदेश को बरकरार रखे हुए है और बस method2() के "लिंक" अधिलेखित कर देता है जो यह ओवरराइड करता है।

JVM का एक कार्यान्वयन इस प्रकार याद है कि BaseClass/method3() हमेशा किसी भी वस्तु इस विधि कभी पर सक्रिय किया जाएगा की आभासी विधि तालिका में तीसरे प्रविष्टि होगी द्वारा invokevirtual के लिए एक कॉल अनुकूलन कर सकते हैं।

invokeinterface के साथ यह अनुकूलन संभव नहीं है। जैसे, आभासी विधि टेबल

AnotherClass 
1. BaseClass/method1() 
2. NextClass/method2() 
3. BaseClass/method3() 
4. AnotherClass/method4() 
5. MyInterface/ifaceMethod() 

MyClass 
1. MyClass/method5() 
2. MyInterface/ifaceMethod()

आप देख सकते हैं में

interface MyInterface { 
    void ifaceMethod(); 
} 

class AnotherClass extends NextClass implements MyInterface { 
    public void method4() { } // overridden from NextClass 
    public void ifaceMethod() { } 
} 

class MyClass implements MyInterface { 
    public void method5() { } 
    public void ifaceMethod() { } 
} 

इस वर्ग पदानुक्रम परिणाम, AnotherClass अपने पांचवें प्रविष्टि में इंटरफेस की विधि शामिल है और MyClass अपनी दूसरी प्रविष्टि में यह होता है। वर्चुअल विधि तालिका में वास्तव में सही प्रविष्टि को खोजने के लिए, invokeinterface वाली विधि के लिए कॉल को हमेशा ऑप्टिमाइज़ेशन की शैली के बिना पूरी तालिका को खोजना होगा, जो कि invokevirtual करता है।

इस तथ्य के अतिरिक्त अंतर हैं कि invokeinterface ऑब्जेक्ट संदर्भों के साथ एक साथ उपयोग किया जा सकता है जो वास्तव में इंटरफ़ेस को लागू नहीं करता है।इसलिए, invokeinterface को रनटाइम पर जांचना होगा कि तालिका में कोई विधि मौजूद है या संभावित रूप से अपवाद फेंकना है। यदि आप विषय में गहराई से गोता लगाने के लिए चाहते हैं, तो मैं सुझाव देता हूं, उदाहरण के लिए, "Efficient Implementation of Java Interfaces: Invokeinterface Considered Harmless"

+4

"हमेशा ऑप्टिमाइज़ेशन की शैली के बिना पूरी तालिका को खोजना है जो अन्वेषण करता है" - यह ध्यान दिया जाना चाहिए कि यह हमेशा * तालिका को खोजना नहीं है, क्योंकि यह अनुकूलन की एक अलग शैली कर सकता है । अधिक जानकारी के लिए जुड़े "माना हानिरहित" पेपर देखें। –

1

JVM Spec में दोनों निर्देशों की तुलना करना, पहला अंतर यह है कि invokevirtual लुकअप के दौरान विधि की पहुंच की जांच करता है, जबकि invokeinterface नहीं करता है।

+0

दिलचस्प है, लेकिन क्या यह सब कुछ हो सकता है? – itsadok

+0

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

संबंधित मुद्दे