जवाबों:
यह एक नया जेवीएम निर्देश है जो एक कंपाइलर को कोड उत्पन्न करने की अनुमति देता है जो पहले की तुलना में एक शिथिल विनिर्देशन के साथ तरीकों को कॉल करता है - यदि आप जानते हैं कि " बतख टाइपिंग " क्या है, तो इनवॉकेन्डेसिक मूल रूप से बतख टाइपिंग की अनुमति देता है। एक जावा प्रोग्रामर के साथ आप ऐसा नहीं कर सकते हैं; यदि आप एक उपकरण निर्माता हैं, तो आप इसका उपयोग अधिक लचीली, अधिक कुशल JVM- आधारित भाषाओं के निर्माण के लिए कर सकते हैं। यहाँ एक बहुत प्यारी ब्लॉग पोस्ट है जो बहुत विस्तार देती है।
MethodHandle
, वह वास्तव में एक ही तरह की चीज है, लेकिन बहुत अधिक लचीलेपन के साथ। लेकिन इस सब में असली शक्ति जावा भाषा के अतिरिक्त नहीं आती है, बल्कि JVM की क्षमताओं में अन्य भाषाओं का समर्थन करने में है जो आंतरिक रूप से अधिक गतिशील हैं।
invokedynamic
जिसके उपयोग से यह प्रदर्शन योग्य हो जाता है (उन्हें एक अनाम आंतरिक-वर्ग में लपेटने की तुलना में जो शुरू करने से पहले लगभग एकमात्र विकल्प था invokedynamic
)। जेवीएम के शीर्ष पर संभवतः बहुत सारी कार्यात्मक प्रोग्रामिंग भाषाएं एनॉन-इनर-क्लासेस के बजाय इसे संकलित करने का विकल्प चुनेंगी।
कुछ समय पहले, C # ने एक शांत सुविधा जोड़ी, C # के भीतर गतिशील वाक्यविन्यास
Object obj = ...; // no static type available
dynamic duck = obj;
duck.quack(); // or any method. no compiler checking.
इसे चिंतनशील विधि कॉल के लिए सिंटैक्स चीनी के रूप में सोचें। इसमें बहुत दिलचस्प अनुप्रयोग हो सकते हैं। http://www.infoq.com/pretations/Statically-Dynamic-Typing-Neal-Gafter देखें
नील गेयर, जो C # के गतिशील प्रकार के लिए जिम्मेदार है, बस SUN से MS तक डिफेक्टेड है। इसलिए यह सोचना अनुचित नहीं है कि SUN के अंदर उन्हीं बातों पर चर्चा की गई थी।
मुझे याद है इसके तुरंत बाद, कुछ जावा दोस्त ने कुछ इसी तरह की घोषणा की
InvokeDynamic duck = obj;
duck.quack();
दुर्भाग्य से, सुविधा नहीं है जहाँ जावा 7 में पाया जाना है। बहुत निराश हैं। जावा प्रोग्रामर के लिए, उनके पास invokedynamic
अपने कार्यक्रमों का लाभ उठाने का कोई आसान तरीका नहीं है ।
invokedynamic
जावा प्रोग्रामर के लिए इस्तेमाल करने का कभी इरादा नहीं था । IMO यह जावा दर्शन को बिल्कुल भी फिट नहीं करता है। इसे गैर-जावा भाषाओं के लिए JVM फीचर के रूप में जोड़ा गया था।
आह्वान करने से पहले समझने के लिए दो अवधारणाएं हैं।
1. स्टेटिक बनाम डायनामिन टाइपिंग
स्टेटिक - संकलित समय पर preforms प्रकार की जाँच (जैसे जावा)
डायनेमिक - प्रीफॉर्म टाइप रनिंग पर चेकिंग (जैसे जावास्क्रिप्ट)
टाइप चेकिंग यह सत्यापित करने की एक प्रक्रिया है कि एक प्रोग्राम टाइप सुरक्षित है, यह है, वर्ग और उदाहरण चर, विधि पैरामीटर, वापसी मान और अन्य चर के लिए टाइप की गई जानकारी की जाँच करना। उदाहरण के लिए, संकलन समय पर स्ट्रिंग, .. के बारे में जावा जानता है, जबकि जावास्क्रिप्ट में किसी वस्तु का प्रकार केवल रनटाइम पर निर्धारित किया जा सकता है
2. मजबूत बनाम कमजोर टाइपिंग
मजबूत - इसके संचालन के लिए दिए गए मूल्यों के प्रकारों पर प्रतिबंध निर्दिष्ट करता है (जैसे जावा)
कमजोर - एक ऑपरेशन के तर्कों को धर्मान्तरित (कास्ट) करता है यदि उन तर्कों में असंगत प्रकार होते हैं (जैसे विज़ुअल बेसिक)
यह जानते हुए कि जावा एक स्टेटिक और कमजोर टाइप है, आप जेवीएम पर डायनेमिक और स्ट्रांगली टाइप की गई भाषाओं को कैसे लागू करते हैं?
चालित कार्य प्रणाली लागू करने के बाद - एक विधि या फ़ंक्शन का सबसे उपयुक्त कार्यान्वयन चुन सकता है जो रनटाइम सिस्टम लागू करता है।
उदाहरण: होने (ए + बी) और संकलन समय पर चर, बी के बारे में कुछ भी नहीं जानना, इस अभियान को रनटाइम में जावा में सबसे उपयुक्त विधि के लिए मैप करता है। जैसे, यदि यह निकलता है, बी स्ट्रिंग्स हैं, तो कॉल विधि (स्ट्रिंग ए, स्ट्रिंग बी)। यदि यह पता चला है कि, बी एक इनट हैं, तो कॉल विधि (इंट ए, इंट बी)।
जावा 7 के साथ इनवॉल्ड डायनामिक पेश किया गया था।
मेरे जावा रिकॉर्ड्स लेख के हिस्से के रूप में , मैंने इनोक डायनामिक के पीछे की प्रेरणा के बारे में व्यक्त किया। आइए इंडी की किसी न किसी परिभाषा से शुरू करें।
डायनामिक इनवॉइस टाइप करें (इसे इंडी के रूप में भी जाना जाता है ) जेएसआर 292 का हिस्सा था, जो डायनेमिक प्रकार की भाषाओं के लिए जेवीएम समर्थन को बढ़ाने के लिए थी। जावा 7 में इसकी पहली रिलीज़ के बाद, invokedynamic
इसके java.lang.invoke
सामान के साथ-साथ ओपकोड का उपयोग जेयूबी जैसी गतिशील JVM- आधारित भाषाओं द्वारा काफी किया गया है।
हालाँकि विशेष रूप से गतिशील भाषा समर्थन को बढ़ाने के लिए तैयार की गई indy, यह उससे कहीं अधिक प्रदान करती है। तथ्य की बात के रूप में, यह प्रयोग करने के लिए उपयुक्त है जहाँ एक भाषा डिजाइनर को गतिशील प्रकार की कलाबाजी से लेकर गतिशील रणनीतियों तक किसी भी प्रकार की गतिशीलता की आवश्यकता होती है!
उदाहरण के लिए, जावा 8 लैम्ब्डा एक्सप्रेशंस वास्तव में उपयोग करके कार्यान्वित किए जाते हैं invokedynamic
, भले ही जावा एक स्टेटिकली टाइप की गई भाषा हो!
कुछ समय के लिए JVM ने चार विधि आह्वान प्रकारों का समर्थन किया: invokestatic
स्थिर विधियों invokeinterface
को कॉल करने के लिए , इंटरफ़ेस विधियों invokespecial
को कॉल करने के लिए, कंस्ट्रक्टरों super()
या निजी तरीकों invokevirtual
को कॉल करने के लिए और उदाहरण के तरीकों को कॉल करने के लिए।
उनके मतभेदों के बावजूद, ये आह्वान प्रकार एक सामान्य विशेषता साझा करते हैं : हम उन्हें अपने तर्क से समृद्ध नहीं कर सकते । इसके विपरीत, invokedynamic
हमें किसी भी तरह से मंगलाचरण प्रक्रिया बूटस्ट्रैप में सक्षम बनाता है। तब JVM सीधे बूटस्ट्रैप्ड विधि को कॉल करने का ध्यान रखता है।
पहली बार JVM एक invokedynamic
निर्देश देखता है , यह एक विशेष स्थैतिक विधि को बूटस्ट्रैप विधि कहता है । बूटस्ट्रैप विधि जावा कोड का एक टुकड़ा है जिसे हमने वास्तविक-टू-इनवॉल्ड लॉजिक तैयार करने के लिए लिखा है:
तब बूटस्ट्रैप विधि का एक उदाहरण देता है java.lang.invoke.CallSite
। यह CallSite
वास्तविक विधि का संदर्भ है, अर्थात MethodHandle
।
अब से, हर बार जेवीएम इस invokedynamic
निर्देश को फिर से देखता है , यह स्लो पाथ को छोड़ देता है और सीधे अंतर्निहित निष्पादन योग्य कहता है। JVM धीमी गति से रास्ता छोड़ना जारी रखता है जब तक कि कुछ बदल न जाए।
जावा 14 Records
उन वर्गों को घोषित करने के लिए एक अच्छा कॉम्पैक्ट सिंटैक्स प्रदान कर रहा है जो गूंगा डेटा धारक हैं।
इस सरल रिकॉर्ड को ध्यान में रखते हुए:
public record Range(int min, int max) {}
इस उदाहरण के लिए बाइटकोड कुछ इस तरह होगा:
Compiled from "Range.java"
public java.lang.String toString();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokedynamic #18, 0 // InvokeDynamic #0:toString:(LRange;)Ljava/lang/String;
6: areturn
इसकी बूटस्ट्रैप विधि तालिका में :
BootstrapMethods:
0: #41 REF_invokeStatic java/lang/runtime/ObjectMethods.bootstrap:
(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;
Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;
Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;
Method arguments:
#8 Range
#48 min;max
#50 REF_getField Range.min:I
#51 REF_getField Range.max:I
इसलिए रिकॉर्ड्स के लिए बूटस्ट्रैप विधि को कहा जाता है bootstrap
जो java.lang.runtime.ObjectMethods
कक्षा में रहती है । जैसा कि आप देख सकते हैं, यह बूटस्ट्रैप विधि निम्नलिखित मापदंडों की अपेक्षा करती है:
MethodHandles.Lookup
लुकअप संदर्भ ( Ljava/lang/invoke/MethodHandles$Lookup
भाग) का प्रतिनिधित्व करने का एक उदाहरण ।toString
, equals
, hashCode
, आदि) बूटस्ट्रैप लिंक जा रहा है। उदाहरण के लिए, जब मूल्य है toString
, बूटस्ट्रैप एक ConstantCallSite
( CallSite
जो कभी नहीं बदलता है) लौटाएगा जो toString
इस विशेष रिकॉर्ड के लिए वास्तविक कार्यान्वयन की ओर इशारा करता है।TypeDescriptor
विधि (के लिए Ljava/lang/invoke/TypeDescriptor
भाग)।Class<?>
, रिकॉर्ड क्लास प्रकार का प्रतिनिधित्व करता है। यह
Class<Range>
इस मामले में है।min;max
।MethodHandle
प्रति घटक एक । इस तरह से बूटस्ट्रैप विधि MethodHandle
इस विशेष विधि के कार्यान्वयन के लिए घटकों के आधार पर बना सकती है ।invokedynamic
अनुदेश बूटस्ट्रैप विधि करने के लिए उन सभी तर्कों से गुजरता है। बूटस्ट्रैप विधि, बदले में, का एक उदाहरण देता है ConstantCallSite
। यह ConstantCallSite
अनुरोधित विधि कार्यान्वयन का संदर्भ है, उदाहरण के लिए toString
।
प्रतिबिंब एपीआई के विपरीत, java.lang.invoke
JVM पूरी तरह से सभी इनवोकेशन के माध्यम से देख सकता है क्योंकि एपीआई काफी कुशल है। इसलिए, JVM सभी प्रकार के अनुकूलन लागू कर सकता है जब तक हम धीमे रास्ते से बचते हैं जितना संभव हो!
दक्षता तर्क के अलावा, इसकी सादगी केinvokedynamic
कारण दृष्टिकोण अधिक विश्वसनीय और कम भंगुर है ।
इसके अलावा, जावा रिकॉर्ड्स के लिए जेनरेट किया गया बाइटकोड संपत्तियों की संख्या से स्वतंत्र है। तो, कम bytecode और तेजी से स्टार्टअप समय।
अंत में, मान लें कि जावा के एक नए संस्करण में एक नया और अधिक कुशल बूटस्ट्रैप विधि कार्यान्वयन शामिल है। साथ invokedynamic
, हमारा ऐप बिना किसी सुधार के इस सुधार का लाभ उठा सकता है। इस तरह हमारे पास कुछ प्रकार के फॉरवर्ड बाइनरी कम्पेटिबिलिटी है । इसके अलावा, यह जिस डायनेमिक रणनीति के बारे में हम बात कर रहे थे!
जावा रिकॉर्ड्स के अलावा, इन्वोक डायनामिक का उपयोग सुविधाओं को लागू करने के लिए किया गया है:
LambdaMetafactory
StringConcatFactory
meth.invoke(args)
। तो कैसेinvokedynamic
साथ फिट बैठता हैmeth.invoke
?