2016-01-16 11 views
10

द्वारा संकलित अंतिम मूल्य बदलें मैंने एक बहुत ही अजीब चीज देखी है कि प्रतिबिंब के माध्यम से अंतिम क्षेत्र को बदलने के बाद, उस क्षेत्र को वापस करने की विधि पुरानी मान दे रही है। मुझे लगता है कि यह जेआईटी कंपाइलर की वजह से हो सकता है।जेआईटी

public class Main 
{ 
private static final Main m = new Main(); 
public static Main getM() 
{ 
    return m; 
} 

public static void main(String args[]) throws Exception 
{ 
    Main m = getM(); 
    int x = 0; 
    for(int i = 0;i<10000000;i++) 
    { 
     if(getM().equals(m)) 
      x ++; 
    } 
    Field f = Main.class.getDeclaredField("m"); 
    f.setAccessible(true); 
    removeFinal(f); 
    Main main1 = new Main(); 
    f.set(null, main1); 
    Main main2 = (Main) f.get(null); 
    Main main3 = getM(); 
    System.out.println(main1.toString()); 
    System.out.println(main2.toString()); 
    System.out.println(main3.toString()); 
} 

private static void removeFinal(Field field) throws NoSuchFieldException, IllegalAccessException 
{ 
    Field modifiersField = Field.class.getDeclaredField("modifiers"); 
    modifiersField.setAccessible(true); 
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
} 
} 

परिणाम है::

यहाँ नमूना कार्यक्रम है

[email protected]3 
[email protected] 
[email protected] 

मैं सोच रहा हूँ, मैं कैसे getM() वापसी अद्यतन मूल्य बना सकते हैं?

+3

कीवर्ड 'अंतिम' कंपाइलर को इनलाइन करने की अनुमति देता है। आपको ऐसा करने की ज़रूरत क्यों है? –

+0

क्या यह जेआईटी को विधि को दोबारा लागू करने का कोई तरीका है? – user3009344

+1

जावैक कंपाइलर, जेआईटी नहीं। –

उत्तर

11

मुझे आश्चर्य है, मैं getM() अपडेट मूल्य को कैसे वापस कर सकता हूं?

फाइनल के साथ, आप नहीं कर सकते। रिटर्निंग "पुराना" मान एक वैध व्यवहार है, JLS 17.5.3:

फिर भी, कई जटिलताओं हैं। यदि अंतिम फ़ील्ड फ़ील्ड फ़ील्ड में निरंतर अभिव्यक्ति (§15.28) में प्रारंभ किया गया है, तो अंतिम फ़ील्ड में परिवर्तन नहीं देखा जा सकता है, क्योंकि उस अंतिम फ़ील्ड के उपयोग को स्थिरता के मूल्य के साथ संकलित समय पर प्रतिस्थापित किया गया है अभिव्यक्ति।

एक और समस्या यह है कि विनिर्देश अंतिम क्षेत्रों के आक्रामक अनुकूलन की अनुमति देता है। एक थ्रेड के भीतर, रीडर को अंतिम क्षेत्र के रीडऑर्डर को अंतिम फ़ील्ड के संशोधनों के साथ अनुमत है जो कि कन्स्ट्रक्टर में नहीं होता है।

उस अध्याय में शामिल निर्देशक उदाहरण देखें।

इस प्रावधान को दूर करने के प्रयासों में स्टैक्स के नीचे ऑप्टिमाइज़र के साथ गड़बड़ करना होगा, और सबसे अच्छा नाजुक होगा। यदि आप फ़ील्ड को संशोधित करना चुन रहे हैं, तो परिभाषा के अनुसार, उन फ़ील्ड को अंतिम नहीं होना चाहिए। यदि आप इसे प्रदर्शन कारणों से चाहते हैं (क्या आप वास्तव में?), तो जेएसआर 2 9 2 "almost final" निर्माण करने के लिए यांत्रिकी प्रदान करता है।

+0

जब मेरे एप्लिकेशन में कुछ तोड़ता है, तो नए छोटे जार को लोड करके, एप्लिकेशन को पुनरारंभ किए बिना समस्या को अस्थायी रूप से ठीक/छिपाने के तरीके हैं स्थिर तरीकों तक पहुंच। कभी-कभी मुझे कुछ ठीक करने के लिए अंतिम फ़ील्ड बदलने की जरूरत होती है। जबकि सामान्य रूप से प्रतिबिंब ऐसे मामलों में ठीक काम करता है, कभी-कभी यह प्रश्न में समस्या के कारण नहीं होता है। तो मुझे लगता है कि उस पर काबू पाने का कोई रास्ता नहीं है। – user3009344

1

यदि आप वास्तव में उस मान को बदलना चाहते हैं, तो आप उस वर्ग को लपेट सकते हैं और गेटर ओवरराइड कर सकते हैं।

शायद आपने "प्रतिनिधि"/"प्रॉक्सी" पैटर्न के बारे में कुछ सुना है।

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