2012-11-24 26 views
10

कहते हैं कि हम निम्नलिखित श्रेणियां होती हैं:क्या अधिकांश जेवीएम अप्रयुक्त तरीकों के लिए स्मृति आवंटित करते हैं?

class DoubleOhSeven { 
    public static void doSomethingClassy(); 
    public static void neverDoThisClassy(); 
} 

class Dude { 
    public void doSomething(); 
    public void neverDoThis(); 
} 

public class Party { 
    public static void main(String[] args){ 
    DoubleOhSeven.doSomething(); 
    Dude guy = new Dude; 
    guy.doSomething(); 
    } 
} 
बेशक

, सभी तरीकों में संकलित किया जाएगा उनके संबंधित .class: अप्रयुक्त स्थिर/उदाहरण तरीकों रन टाइम पर स्मृति पर कब्जा करते हैं? अप्रयुक्त विरासत या आयातित तरीकों के बारे में क्या?

उत्तर

12

अप्रयुक्त विधियां अभी भी कक्षा/वस्तु के हिस्से के रूप में स्मृति पर कब्जा कर रही हैं, भले ही उन्हें सीधे नहीं कहा जाता है।

यदि उन्हें अनुकूलित किया गया था, तो इससे इन विधियों पर प्रतिबिंबित कॉल असंभव हो जाएंगी।

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

अप्रयुक्त विरासत विधियां बिल्कुल वही होंगी।

+0

क्या आप किसी अन्य वर्ग से प्रतिबिंबित कॉल का मतलब है? – fny

+0

@ फ़ारज़ या वह वर्ग स्वयं - चूंकि प्रतिबिंबित विधि कॉल, परिभाषा के अनुसार, रनटाइम पर निर्णय लेती है और समय संकलित नहीं करती है, संकलक के पास यह जानने का कोई तरीका नहीं है कि प्रतिबिंबित विधियों को कब या कब कहा जाएगा। – berry120

1

अप्रयुक्त विधियों वर्ग के आकार में प्रवेश करते हैं, लेकिन कक्षाओं को एक तथाकथित PermGen स्मृति में संग्रहीत किया जाता है। ढेर स्मृति, जहां नियमित जावा वस्तुओं को संग्रहीत किया जाता है, वर्ग आकार

3

कक्षा Abc के उदाहरण द्वारा उपयोग की जाने वाली स्मृति इस बात पर निर्भर नहीं है कि Abc में कितनी विधियां हैं।

जेनरेट बाइटकोड स्पष्ट रूप से आकार में वृद्धि करता है जब आप विधियां जोड़ते हैं, चाहे वे कुछ करते हैं या नहीं, लेकिन यह केवल क्लास ऑब्जेक्ट Abc.class के आकार को प्रभावित करेगा, जो केवल एक बार लोड होता है, भले ही कितने उदाहरण बनाए गए हों ।

2

के बाद से वर्गों (है कि जावा 8 के लिए बदल जाएगा), तो आप कुछ इस तरह पहली बार चलाने कर सकते हैं, सूर्य हॉटस्पॉट JVMs के लिए वहाँ PermGen में सफ़ेद रहे हैं:

 

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); 
long before = memoryMXBean.getNonHeapMemoryUsage().getUsed(); 
new Dude(); // class must not be loaded before 
System.out.println("Usage of dude is " + (memoryMXBean.getNonHeapMemoryUsage().getUsed() - before) + " bytes"); 
 

और तुम कुछ इस तरह देखेंगे: दोस्त की प्रयोग 6432 बाइट्स

है और फिर अप्रयुक्त विधि के बिना परीक्षण एक Dude वर्ग बना सकते हैं और चलाएँ:

 

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); 
long before = memoryMXBean.getNonHeapMemoryUsage().getUsed(); 
new DudeWithoutNeverDoThis(); // must not be loaded before 
System.out.println("Usage of dude without 'nerverDoThis' is " + (memoryMXBean.getNonHeapMemoryUsage().getUsed() - before) + " bytes"); 
 

और आप अंतर देखेंगे

+0

कक्षा पर एक विधि के बाद संख्याओं को फिर से प्राप्त करना दिलचस्प होगा, और फिर 1000 बार कहा जाता है। विधि को कॉल करने से कई बार हॉटस्पॉट को मूल कोड में संकलित करने में उत्तेजित किया जाता है, जो स्मृति को ले जाएगा। –

0

विधि संकलित और PerGen को लोड किया जा सकता ('nerverDoThis' बिना दोस्त के प्रयोग 6176 बाइट्स है)।

लेकिन method inlining का उपयोग कर JVM शायद optimize विधि।

उदाहरण के लिए:

public class Test { 

    public void foo(){ 
     System.out.println("foo"); 
     bar(); 
    } 

    public void bar(){ 
     System.out.println("bar"); 
    } 
} 

विधि JIT कम्पाइलर द्वारा इस तरह संकलित किया जाएगा:

public void foo(){ 
    System.out.println("foo"); 
    System.out.println("bar"); 
} 

तो, खाली विधि लागू किया जा कभी नहीं होगा।