2011-12-16 5 views
7

कुछ जावा बाइट कोड पार्सर परियोजना के लिए मैं JVM कल्पना पढ़ सकते हैं और पता लगा कि जावा आभासी मशीन वर्ग फ़ाइल स्वरूप का उपयोग आपरिवर्तक क्षेत्रों के बिट मुखौटा मूल्योंJVM बाइटकोड एक्सेस संशोधक ध्वज 0x1000 (हेक्स) "सिंथेटिक" सेट कब होता है?

ACC_PUBLIC = 0x0001 
    ACC_FINAL = 0x0010 
    ACC_SUPER = 0x0020 # old invokespecial instruction semantics (Java 1.0x?) 
    ACC_INTERFACE = 0x0200 
    ACC_ABSTRACT = 0x0400 
    ACC_SYNTHETIC = 0x1000 
    ACC_ANNOTATION = 0x2000 
    ACC_ENUM = 0x4000 

किसी तरह मैं पता नहीं क्या 0x1000 के लिए है कर रहे हैं । मैंने इसे एक बार आंतरिक कक्षा में देखा, लेकिन तब से मैंने देखा कि सभी आंतरिक वर्गों के लिए, यह ध्वज कभी सेट नहीं किया गया था। क्या अब आप इस झंडे का अर्थ क्या हैं और कहां सेट किया गया है?

उत्तर

6

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

आप पहले से ही एक उदाहरण है जहां सिंथेटिक तत्वों जावा संकलक द्वारा डाला जाता है के रूप में इनर क्लासों उल्लेख किया है, इसलिए हमें इस तरह के एक वर्ग पर ध्यान दें:

class Foo { 

    private String foo; 

    class Bar { 

    private Bar() { } 

    String bar() { 
     return foo; 
    } 
    } 

    Bar bar() { 
    return new Bar(); 
    } 
} 

यह बिल्कुल ठीक है, लेकिन सिंथेटिक तत्वों के बिना संकलित, यह होगा एक जेवीएम द्वारा मना कर दिया गया है जो आंतरिक कक्षाओं के बारे में कुछ नहीं जानता है। जावा कम्पाइलर की तरह कुछ करने के लिए ऊपर वर्ग desugares निम्नलिखित:

class Foo { 

    private String foo; 

    String access$100() { // synthetic method 
    return foo; 
    } 

    Foo$Bar bar() { 
    return new Foo$Bar(this, (Foo$1)null); 
    } 

    Foo() { } // NON-synthetic, but implicit! 
} 

class Foo$Bar { 

    private final Foo $this; // synthetic field 

    private Foo$Bar(Foo $this) { // synthetic parameter 
    this.$this = $this; 
    } 

    Foo$Bar(Foo $this, Foo$1 unused) { // synthetic constructor 
    this($this); 
    } 

    String bar() { 
    return $this.access$100(); 
    } 
} 

class Foo$1 { /*empty, no constructor */ } // synthetic class 

के रूप में कहा, JVM इनर क्लासों के बारे में पता नहीं है, लेकिन सदस्यों के निजी उपयोग, यानी एक आंतरिक वर्ग का उपयोग करने में सक्षम नहीं होगा लागू करता है इसके संलग्न वर्ग 'निजी गुण। इस प्रकार, जावा कम्पाइलर अपने गैर दृश्य गुण को बेनकाब करने के क्रम में एक पहुँचा वर्ग के लिए accessors तथाकथित जोड़ने की जरूरत है:

  1. foo क्षेत्र निजी है और इसलिए केवल Foo से एक्सेस किया जा सकता है। access$100 विधि इस फ़ील्ड को अपने पैकेज में दिखाती है जिसमें एक आंतरिक कक्षा हमेशा पाई जाती है। यह विधि सिंथेटिक है क्योंकि इसे कंपाइलर द्वारा जोड़ा जाता है।

  2. Bar कन्स्ट्रक्टर निजी है और इसलिए इसे केवल अपनी कक्षा के भीतर से ही बुलाया जा सकता है। Bar के उदाहरण को तुरंत चालू करने के लिए, एक और (सिंथेटिक) कन्स्ट्रक्टर को एक उदाहरण के निर्माण का पर्दाफाश करने की आवश्यकता है। हालांकि, रचनाकारों का एक निश्चित नाम होता है (आंतरिक रूप से, उन्हें सभी <init> कहा जाता है), इस प्रकार हम विधि एक्सेसर्स के लिए तकनीक लागू नहीं कर सकते हैं, जहां हमने उन्हें access$xxx नाम दिया है। इसके बजाए, हम कृत्रिम प्रकार Foo$1 बनाकर रचनाकार एक्सेसर्स अद्वितीय बनाते हैं।

  3. अपने बाहरी उदाहरण तक पहुंचने के लिए, एक आंतरिक वर्ग को इस उदाहरण के संदर्भ को स्टोर करने की आवश्यकता होती है जो सिंथेटिक फ़ील्ड $this में संग्रहीत होती है। इस संदर्भ को कन्स्ट्रक्टर में सिंथेटिक पैरामीटर द्वारा आंतरिक आवृत्ति को सौंपने की आवश्यकता है।

सिंथेटिक तत्वों के लिए अन्य उदाहरण वर्गों कि लैम्ब्डा भाव का प्रतिनिधित्व करते हैं, पुल तरीकों जब एक प्रकार-अलग हस्ताक्षरों के साथ तरीकों अधिभावी कर रहे हैं, Proxy वर्ग या वर्गों Maven जैसे अन्य टूल द्वारा बनाई गई हैं कि के निर्माण बनाता है या क्रम कोड जनरेटर जैसे Byte Buddy (लापरवाही प्लग)।

3

यह "कृत्रिम" झंडा है, जब संकलक द्वारा फ़ील्ड या विधि उत्पन्न होती है। AFAIK यह आंतरिक कक्षाओं के लिए है, जो आपके अवलोकन के साथ मेल खाता है, और सेट किया जाना चाहिए जब एक आर्टिफैक्ट स्रोत कोड में प्रकट नहीं होता है।

http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88571

+0

संकेत के लिए धन्यवाद। मैंने तदनुसार सवाल अपडेट किया। –

+0

@PeterKofler अपडेट किया गया। –

+0

कहता है "एक वर्ग सदस्य जो स्रोत कोड में प्रकट नहीं होता है उसे सिंथेटिक विशेषता का उपयोग करके चिह्नित किया जाना चाहिए।" क्या इसका मतलब है कि सिंथेटिक सदस्य को '0x1000' एक्सेस संशोधक (' u2 access_flags' में) के साथ भी चिह्नित किया गया है? यह स्पष्ट नहीं है। –

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