जवाबों:
हाँ, Java bytecode का संकलन मशीन कोड के संकलन से अधिक आसान है। यह आंशिक रूप से है क्योंकि लक्ष्य के लिए केवल एक प्रारूप है (मैनड्रिल उल्लेख के रूप में, हालांकि यह केवल संकलक जटिलता को कम करता है, संकलन समय नहीं), आंशिक रूप से क्योंकि जेवीएम एक बहुत ही सरल मशीन है और वास्तविक सीपीयू की तुलना में प्रोग्राम के लिए अधिक सुविधाजनक है - जैसा कि इसमें डिज़ाइन किया गया है। जावा भाषा के साथ अग्रानुक्रम, अधिकांश जावा संचालन मानचित्र एक बहुत ही सरल तरीके से बिल्कुल एक बायटेकोड संचालन के लिए मैप करते हैं। एक और बहुत महत्वपूर्ण कारण यह है कि व्यावहारिक रूप से नहींअनुकूलन होता है। लगभग सभी दक्षता चिंताओं को जेआईटी कंपाइलर (या संपूर्ण रूप से जेवीएम) पर छोड़ दिया जाता है, इसलिए सामान्य कंपाइलरों का पूरा मध्य छोर गायब हो जाता है। यह मूल रूप से एक बार एएसटी के माध्यम से चल सकता है और प्रत्येक नोड के लिए तैयार-निर्मित बायटेकोड अनुक्रम उत्पन्न कर सकता है। एलएलबीएम, कहने की जटिलताओं की तुलना में विधि तालिकाओं, निरंतर पूल आदि के निर्माण के कुछ "प्रशासनिक ओवरहेड" है, लेकिन यह कुछ भी नहीं है।
एक कंपाइलर केवल एक प्रोग्राम है जो मानव-पठनीय 1 पाठ फ़ाइलों को लेता है और उन्हें मशीन के लिए द्विआधारी निर्देशों में अनुवाद करता है। यदि आप एक कदम पीछे लेते हैं और इस सैद्धांतिक दृष्टिकोण से अपने प्रश्न के बारे में सोचते हैं, तो जटिलता लगभग एक ही है। हालांकि, अधिक व्यावहारिक स्तर पर, बाइट कोड कंपाइलर सरल हैं।
किसी कार्यक्रम को संकलित करने के लिए क्या व्यापक कदम उठाने होंगे?
दोनों के बीच केवल दो वास्तविक अंतर हैं।
सामान्य तौर पर, कई संकलन इकाइयों के साथ एक प्रोग्राम को मशीन कोड के संकलन के समय लिंक करने की आवश्यकता होती है और आमतौर पर बाइट कोड के साथ नहीं होती है। कोई इस बारे में बाल विभाजित कर सकता है कि क्या लिंकिंग इस प्रश्न के संदर्भ में संकलन का हिस्सा है। यदि हां, तो बाइट कोड संकलन थोड़ा सरल होगा। हालाँकि, लिंकिंग की जटिलता रन-टाइम के लिए बनी होती है जब कई लिंकिंग चिंताओं को VM द्वारा नियंत्रित किया जाता है (नीचे दिए गए मेरे लिंक देखें)।
बाइट कोड कंपाइलर ज्यादा ऑप्टिमाइज़ नहीं करते हैं क्योंकि वीएम फ्लाई पर यह बेहतर कर सकता है (जेआईटी कंपाइलर आजकल वीएम के लिए एक मानक मानक है)।
इससे मैं यह निष्कर्ष निकालता हूं कि बाइट कोड कंपाइलर इन दोनों को वीएम रनटाइम के लिए सबसे अधिक अनुकूलन और सभी लिंकिंग की जटिलता को छोड़ सकते हैं। बाइट कोड कंपाइलर अभ्यास में सरल होते हैं क्योंकि वे वीएम पर कई जटिलताओं को दूर करते हैं जो मशीन कोड कंपाइलर स्वयं लेते हैं।
1 गूढ़ भाषाओं की गिनती नहीं
मैं कहूंगा कि कंपाइलर डिज़ाइन को सरल बनाता है क्योंकि संकलन हमेशा जावा से जेनेरिक वर्चुअल मशीन कोड होता है। इसका मतलब यह भी है कि आपको केवल एक बार कोड संकलित करने की आवश्यकता है और यह किसी भी प्लेटफ़ॉर्म (प्रत्येक मशीन पर संकलन करने के बजाय) पर चलेगा। मुझे यकीन नहीं है कि यदि संकलन का समय कम होगा क्योंकि आप एक मानकीकृत मशीन की तरह आभासी मशीन पर विचार कर सकते हैं।
दूसरी ओर, प्रत्येक मशीन में जावा वर्चुअल मशीन भरी होगी ताकि वह "बाइट कोड" की व्याख्या कर सके (जो कि जावा कोड संकलन के परिणामस्वरूप वर्चुअल मशीन कोड है), इसे वास्तविक मशीन कोड में अनुवाद करें और इसे चलाएं ।
Imo यह बहुत बड़े कार्यक्रमों के लिए अच्छा है लेकिन छोटे लोगों के लिए बहुत बुरा है (क्योंकि वर्चुअल मशीन मेमोरी की बर्बादी है)।
संकलन की जटिलता काफी हद तक स्रोत भाषा और लक्ष्य भाषा और इस अंतराल को पाटने के दौरान आप जिस स्तर के अनुकूलन को लागू करना चाहते हैं, उसके बीच के शब्दार्थ अंतर पर निर्भर करती है।
उदाहरण के लिए, जावा स्रोत कोड को जेवीएम बाइट कोड के लिए संकलित करना अपेक्षाकृत आगे की ओर है, क्योंकि जावा का एक मुख्य उपसमूह है जो सीधे जेवीएम बाइट कोड के सबसेट के लिए मैप करता है। कुछ अंतर हैं: जावा में लूप हैं लेकिन नहीं GOTO
, जेवीएम के पास GOTO
लेकिन कोई लूप नहीं है, जावा में जेनेरिक है, जेवीएम नहीं है, लेकिन उन लोगों से आसानी से निपटा जा सकता है (छोरों से सशर्त छलांग में परिवर्तन तुच्छ है, टाइप इरेज़र थोड़ा कम इसलिए, लेकिन अभी भी प्रबंधनीय है)। अन्य अंतर हैं लेकिन कम गंभीर हैं।
रूबी स्रोत कोड को जेवीएम बाइट कोड में संकलित करना बहुत अधिक शामिल है (विशेष रूप से पहले invokedynamic
और MethodHandles
जावा 7 में पेश किया गया था, या जेवीएम कल्पना के तीसरे संस्करण में अधिक सटीक रूप से)। रूबी में, तरीकों को रनटाइम पर बदला जा सकता है। जेवीएम पर, कोड की सबसे छोटी इकाई जिसे रनटाइम पर प्रतिस्थापित किया जा सकता है, एक वर्ग है, इसलिए रूबी विधियों को जेवीएम विधियों के लिए नहीं बल्कि जेवीएम कक्षाओं के लिए संकलित किया जाना है। रूबी विधि प्रेषण जेवीएम विधि प्रेषण से मेल नहीं खाता है और इससे पहले invokedynamic
, जेवीएम में अपने स्वयं के विधि प्रेषण तंत्र को इंजेक्ट करने का कोई तरीका नहीं था। रूबी में निरंतरता और कॉरटाइन्स हैं, लेकिन जेवीएम में उन्हें लागू करने के लिए सुविधाओं का अभाव है। (जेवीएम केGOTO
विधि के भीतर लक्ष्य को कूदने तक सीमित है।) जेवीएम पर एकमात्र नियंत्रण प्रवाह आदिम है, जो निरंतरता को लागू करने के लिए पर्याप्त शक्तिशाली होगा और अपवादों को लागू करने के लिए, दोनों बेहद भारी हैं, जबकि कोरटाइन का पूरा उद्देश्य है बहुत हल्के रहो।
OTOH, रूबिनस बाइट कोड या YARV बाइट कोड के लिए रूबी स्रोत कोड का संकलन फिर से तुच्छ है, क्योंकि उन दोनों को स्पष्ट रूप से रूबी के लिए संकलन लक्ष्य के रूप में तैयार किया गया है (हालांकि रूबिनियस का उपयोग अन्य नामों जैसे कि CoffeeScript और सबसे प्रसिद्ध फैंसी के लिए किया गया है) ।
इसी तरह, जेवीएम बाइट कोड के लिए x86 देशी कोड को संकलित करना सीधे-आगे नहीं है, फिर से, एक बहुत बड़ा अर्ध-अंतराल है।
हास्केल एक और अच्छा उदाहरण है: हास्केल के साथ, कई उच्च-प्रदर्शन, औद्योगिक ताकत उत्पादन-तैयार कंपाइलर हैं जो देशी x86 मशीन कोड का उत्पादन करते हैं, लेकिन इस तिथि तक, जेवीएम या सीएलआई के लिए कोई काम करने वाला कंपाइलर नहीं है, क्योंकि सिमेंटिक गैप इतना बड़ा है कि इसे पाटना बहुत जटिल है। तो, यह एक उदाहरण है जहां देशी मशीन कोड का संकलन वास्तव में JVM या CIL बाइट कोड के संकलन की तुलना में कम जटिल है। इसका कारण यह है कि देशी मशीन कोड में निम्न स्तर के प्राइमेटिव्स ( GOTO
, पॉइंटर्स,…) होते हैं, जो उच्च स्तरीय प्राइमेटिव्स जैसे कि मैथड कॉल या अपवादों का उपयोग करने की तुलना में आप जो करना चाहते हैं, उसे करना "आसान" हो सकता है।
इसलिए, कोई यह कह सकता है कि लक्ष्य भाषा जितनी उच्च स्तर की है, उतनी ही बारीकी से उसे संकलक की जटिलता को कम करने के लिए स्रोत भाषा के शब्दार्थ से मेल खाना है।
व्यवहार में, अधिकांश JVM आज बहुत जटिल सॉफ्टवेयर हैं, JIT संकलन कर रहे हैं (इसलिए bytecode गतिशील रूप से JVM द्वारा मशीन कोड में अनुवादित है)।
तो जबकि जावा स्रोत कोड (या क्लोजर सोर्स कोड) से जेवीएम बाइट कोड तक संकलन वास्तव में सरल है, जेवीएम खुद मशीन कोड में जटिल अनुवाद कर रहा है।
तथ्य यह है कि जेवीएम के अंदर यह जेआईटी अनुवाद गतिशील है जेवीएम को बायोटेक के सबसे प्रासंगिक हिस्सों पर ध्यान केंद्रित करने में सक्षम बनाता है। व्यावहारिक रूप से, अधिकांश जेवीएम जेवीएम बायोटेक के सबसे गर्म भागों (जैसे कि सबसे अधिक तथाकथित तरीके, या सबसे निष्पादित बुनियादी ब्लॉक) का अनुकूलन करते हैं।
मुझे यकीन नहीं है कि जेवीएम + जावा की संयुक्त जटिलता बायटेकोड संकलक से आगे के समय के संकलक की जटिलता से काफी कम है।
यह भी देखें कि अधिकांश पारंपरिक संकलक (जैसे जीसीसी या क्लैंग / एलएलवीएम ) इनपुट सी (या सी ++, या एडा, ...) स्रोत कोड को एक आंतरिक प्रतिनिधित्व में बदल रहे हैं ( GCC के लिए Gimple , Clang के लिए LLVM) जो काफी समान है कुछ बाइटकोड। फिर वे उस आंतरिक अभ्यावेदन को परिवर्तित कर रहे हैं (पहले इसे अपने आप में अनुकूलित कर रहे हैं, अर्थात अधिकांश GCC अनुकूलन पास कर रहे हैं और इनपुट के रूप में Gimple का उत्पादन कर रहे हैं; बाद में कोड से कोडांतरक या मशीन कोड का उत्सर्जन करते हैं) ऑब्जेक्ट कोड में।
BTW, हाल ही में GCC (विशेष रूप से libgccjit ) और LLVM अवसंरचना के साथ, आप उन्हें अपने आंतरिक गिमल या LLVM अभ्यावेदन में कुछ अन्य (या अपनी खुद की) भाषा संकलित करने के लिए उपयोग कर सकते हैं, फिर मध्य-अंत और पीछे की कई अनुकूलन क्षमताओं से लाभ- इन संकलक के अंत भागों।