2009-04-16 19 views
16

संदर्भित हैं, मुझे प्रोग्रामेटिक रूप से यह पता लगाना होगा कि किसी दिए गए जावा ऑब्जेक्ट पर कितनी मेमोरी है, जिसमें ऑब्जेक्ट्स द्वारा कब्जा कर लिया गया स्मृति शामिल है।प्रोग्राम ऑब्जेक्ट्स द्वारा जावा ऑब्जेक्ट पर कब्जा कर लिया गया स्मृति की गणना करें जिसमें ऑब्जेक्ट्स

मैं एक मेमोरी ढेर डंप उत्पन्न कर सकता हूं और एक उपकरण का उपयोग कर परिणामों का विश्लेषण कर सकता हूं। हालांकि, एक हीप डंप उत्पन्न करने के लिए काफी समय लगता है और ऐसे उपकरण के लिए रिपोर्ट उत्पन्न करने के लिए डंप को पढ़ने के लिए। इस तथ्य को देखते हुए कि मुझे शायद इसे कई बार करने की ज़रूरत होगी, अगर मैं अपने प्रोजेक्ट में कुछ कोड डाल सकता हूं तो मेरा काम बहुत अधिक चुस्त होगा जो मुझे यह "रनटाइम" मान देगा।

मैं इसे कैसे प्राप्त कर सकता हूं?

ps: विशेष रूप से मैं आपको लगता है कि के लिए प्रतिबिंब का उपयोग करने की आवश्यकता होगी प्रकार javax.xml.transform.Templates

+0

मैं इसे एक सटीक डुप्ली नहीं कहूंगा। – Inisheer

+0

ठीक है, वास्तव में एक डुप्ली नहीं है, क्योंकि मूल प्रश्न इस संदर्भ में उत्तर देने योग्य उत्तर प्रदान करने में विफल रहा है ... – Varkhan

+0

यह कई प्रदान करता है। – erickson

उत्तर

11

की वस्तुओं का संग्रह है। कोड के परिणामस्वरूप टुकड़ा जटिल मुझे यहाँ पोस्ट करने के लिए (हालांकि यह जल्द ही एक जीपीएल टूलकिट मैं निर्माण कर रहा हूँ के हिस्से के रूप में उपलब्ध हो जाएगा) है, लेकिन मुख्य विचार है:

  • एक वस्तु हैडर 8 बाइट्स का उपयोग करता है (वर्ग सूचक और संदर्भ गिनती)
  • प्रत्येक आदिम क्षेत्र 1 का उपयोग करता है, 2, 4 या वास्तविक प्रकार
  • प्रत्येक वस्तु संदर्भ के आधार पर 8 बाइट्स (यानी गैर आदिम) क्षेत्र 4 बाइट (संदर्भ का उपयोग करता है, के साथ साथ के लिए जो कुछ भी संदर्भित ऑब्जेक्ट का उपयोग करता है)

आपको सरणी अलग से इलाज करने की आवश्यकता है (8 द्वारा हेडर के टेस, लम्बाई के 4 बाइट्स, 4 * लंबाई के बाइट बाइट्स, साथ ही जो वस्तुएं अंदर आ रही हैं)। आपको प्रतिबिंब का उपयोग करके खेतों (और इसके माता-पिता के खेतों) के माध्यम से पुनरावृत्ति के अन्य प्रकार की वस्तुओं को संसाधित करने की आवश्यकता है।

आपको रिकर्सन के दौरान "देखी गई" वस्तुओं का एक सेट रखने की भी आवश्यकता है, ताकि कई स्थानों पर कई बार ऑब्जेक्ट्स को संदर्भित न किया जा सके।

+2

इसके लायक होने के लिए, ऑब्जेक्ट हेडर कम से कम इतना उपयोग करता है, लेकिन मुझे लगता है कि पुराने जेवीएम अधिक उपयोग करते हैं। सरल परीक्षण कोड द्वारा भी यह सत्यापित करने के लिए आसान (पर्याप्त) है (एक लाख वस्तुओं को बनाओ, जीसी, थोड़ा सो जाओ, मुफ्त मेमोरी देखें - सैद्धांतिक रूप से काम करने की गारंटी नहीं है, अभ्यास में)। – StaxMan

+2

इसके अलावा: 4 बाइट 32-बिट संदर्भों के लिए है। मुझे लगता है कि 64-बिट सिस्टम 8 बाइट्स के लिए। – StaxMan

+0

वैसे मैं थोड़ी देर के लिए भी सोच रहा था, लेकिन उस पर कोई संदर्भ नहीं मिला ... इसलिए मैंने स्टैक्समैन के वर्णन के रूप में कुछ बेंचमार्किंग की कोशिश की, और ऐसा लगता है कि यह अभी भी 4 है ... आंकड़े जाओ। – Varkhan

3

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

public class Sizeof { 
     public static void main(String[] args) 
      throws Exception { 
     // "warm up" all classes/methods that we are going to use: 
     runGC(); 
     usedMemory(); 

     // array to keep strong references to allocated objects: 
     final int count = 10000; // 10000 or so is enough for small ojects 
     Object[] objects = new Object[count]; 

     long heap1 = 0; 

     // allocate count+1 objects, discard the first one: 
     for (int i = -1; i < count; ++i) { 
      Object object; 

    //// INSTANTIATE YOUR DATA HERE AND ASSIGN IT TO 'object': 


      object=YOUR OBJECT; 
    ////end your code here 
      if (i >= 0) { 
      objects[i] = object; 
      } 
      else { 
      object = null; // discard the "warmup" object 
      runGC(); 
      heap1 = usedMemory(); // take a "before" heap snapshot 
      } 
     } 

     runGC(); 
     long heap2 = usedMemory(); // take an "after" heap snapshot: 

     final int size = Math.round(((float)(heap2 - heap1))/count); 
     System.out.println("'before' heap: " + heap1 + 
          ", 'after' heap: " + heap2); 
     System.out.println("heap delta: " + (heap2 - heap1) + 
          ", {" + objects[0].getClass() + "} size = " + size + " bytes"); 
     } 

     // a helper method for creating Strings of desired length 
     // and avoiding getting tricked by String interning: 
     public static String createString(final int length) { 
     final char[] result = new char[length]; 
     for (int i = 0; i < length; ++i) { 
      result[i] = (char)i; 
     } 

     return new String(result); 
     } 

     // this is our way of requesting garbage collection to be run: 
     // [how aggressive it is depends on the JVM to a large degree, but 
     // it is almost always better than a single Runtime.gc() call] 
     private static void runGC() 
      throws Exception { 
     // for whatever reason it helps to call Runtime.gc() 
     // using several method calls: 
     for (int r = 0; r < 4; ++r) { 
      _runGC(); 
     } 
     } 

     private static void _runGC() 
      throws Exception { 
     long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE; 

     for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++i) { 
      s_runtime.runFinalization(); 
      s_runtime.gc(); 
      Thread.currentThread().yield(); 

      usedMem2 = usedMem1; 
      usedMem1 = usedMemory(); 
     } 
     } 

     private static long usedMemory() { 
     return s_runtime.totalMemory() - s_runtime.freeMemory(); 
     } 

     private static final Runtime s_runtime = Runtime.getRuntime(); 

    } // end of class 
+1

यह इस तथ्य के आधार पर त्रुटिपूर्ण है कि जीसी() और रनफिनलाइजेशन() विधियां निर्धारित नहीं हैं। आईई .: वे केवल उन कार्यों को करने के लिए रनटाइम पर संकेत देते हैं। रनटाइम के लिए उन्हें अनदेखा करना पूरी तरह कानूनी है। –

+1

यह त्रुटिपूर्ण नहीं है - कभी-कभी आपको अनदेखा किया जाएगा जैसा कि आप कहते हैं, यही कारण है कि बड़ी संख्या में पुनरावृत्तियों और परिणामों का औसत। – Peter

+1

आप कम से कम इस कोड के स्रोत को श्रेय दे सकते थे, भले ही आपने इसे थोड़ा सा tweaked किया हो: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html – wolfcastle

6

ऐसा लगता है कि पहले से ही इस Classmexer कहा जाता है करने के लिए एक उपयोगिता है की तरह।

मैंने इसे स्वयं नहीं किया है, लेकिन मैं अपना रास्ता घुमाने से पहले उस मार्ग पर जाऊंगा।

+1

+1। –

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

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