java - जावा में, ऑब्जेक्ट के आकार को निर्धारित करने का सबसे अच्छा तरीका क्या है?




memory (16)

अगर आप यह जानना चाहते हैं कि आपके जेवीएम में कितनी मेमोरी का इस्तेमाल किया जा रहा है, और कितना मुफ्त है, तो आप इस तरह कुछ कोशिश कर सकते हैं:

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

संपादित करें: मैंने सोचा कि यह सहायक हो सकता है क्योंकि प्रश्न लेखक ने यह भी कहा कि वह तर्क चाहते हैं जो "32 एमबी मेमोरी का उपयोग करने तक जितनी संभव हो उतनी पंक्तियों को पढ़े।"

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

अभी, मेरे पास कोड है जो 32,000 पंक्तियों को पढ़ता है, लेकिन मैं कोड भी लेना चाहता हूं जो कि जितनी संभव हो उतनी पंक्तियों को पढ़ता है जब तक कि मैंने 32 एमबी मेमोरी का उपयोग नहीं किया हो। शायद यह एक अलग सवाल है, लेकिन मैं अभी भी जानना चाहता हूं।


अन्य उत्तरों में से अधिकांश उत्तर उथले आकार प्रदान करते हैं - उदाहरण के लिए किसी भी कुंजी या मूल्यों के बिना हैश मैप का आकार, जो आप चाहते हैं कि संभवतः नहीं है।

जैम प्रोजेक्ट ऊपर java.lang.inस्ट्रुमेंटेशन पैकेज का उपयोग करता है लेकिन पेड़ पर चलता है और इसलिए आपको गहरी मेमोरी उपयोग दे सकता है।

new MemoryMeter().measureDeep(myHashMap);

https://github.com/jbellis/jamm


आपको jol , ओपनजेडीके प्रोजेक्ट के हिस्से के रूप में विकसित टूल का उपयोग करना चाहिए।

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

प्राइमेटिव्स, संदर्भ और सरणी तत्वों के आकार प्राप्त करने के लिए, VMSupport.vmDetails() उपयोग करें। ओरेकल जेडीके 1.8.0_40 पर 64-बिट विंडोज़ (सभी निम्नलिखित उदाहरणों के लिए उपयोग किया जाता है) पर चल रहा है, यह विधि वापस आती है

Running 64-bit HotSpot VM.
Using compressed oop with 0-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

आप ClassLayout.parseClass(Foo.class).toPrintable() का उपयोग कर किसी ऑब्जेक्ट इंस्टेंस के उथले आकार को प्राप्त कर सकते हैं ClassLayout.parseClass(Foo.class).toPrintable() (वैकल्पिक रूप से एक उदाहरण को toPrintable करने toPrintable ) को पास कर सकते हैं। यह केवल उस वर्ग के एक उदाहरण द्वारा उपभोग की गई जगह है; इसमें उस वर्ग द्वारा संदर्भित किसी अन्य वस्तु को शामिल नहीं किया गया है। इसमें ऑब्जेक्ट हेडर, फ़ील्ड संरेखण और पैडिंग के लिए वीएम ओवरहेड शामिल है। java.util.regex.Pattern लिए। java.util.regex.Pattern :

java.util.regex.Pattern object internals:
 OFFSET  SIZE        TYPE DESCRIPTION                    VALUE
      0     4             (object header)                01 00 00 00 (0000 0001 0000 0000 0000 0000 0000 0000)
      4     4             (object header)                00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
      8     4             (object header)                cb cf 00 20 (1100 1011 1100 1111 0000 0000 0010 0000)
     12     4         int Pattern.flags                  0
     16     4         int Pattern.capturingGroupCount    1
     20     4         int Pattern.localCount             0
     24     4         int Pattern.cursor                 48
     28     4         int Pattern.patternLength          0
     32     1     boolean Pattern.compiled               true
     33     1     boolean Pattern.hasSupplementary       false
     34     2             (alignment/padding gap)        N/A
     36     4      String Pattern.pattern                (object)
     40     4      String Pattern.normalizedPattern      (object)
     44     4        Node Pattern.root                   (object)
     48     4        Node Pattern.matchRoot              (object)
     52     4       int[] Pattern.buffer                 null
     56     4         Map Pattern.namedGroups            null
     60     4 GroupHead[] Pattern.groupNodes             null
     64     4       int[] Pattern.temp                   null
     68     4             (loss due to the next object alignment)
Instance size: 72 bytes (reported by Instrumentation API)
Space losses: 2 bytes internal + 4 bytes external = 6 bytes total

आप GraphLayout.parseInstance(obj).toFootprint() का उपयोग कर ऑब्जेक्ट आवृत्ति के गहरे आकार का सारांश दृश्य प्राप्त कर सकते हैं। बेशक, पदचिह्न में कुछ वस्तुओं को साझा किया जा सकता है (अन्य ऑब्जेक्ट्स से भी संदर्भित किया जा सकता है), इसलिए यह उस स्थान की अतिप्रवाह है जिसे उस वस्तु को पुनः प्राप्त किया जा सकता है जब उस वस्तु को कचरा इकट्ठा किया जाता है। Pattern.compile("^[a-zA-Z0-9_.+-][email protected][a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$") के परिणामस्वरूप Pattern.compile("^[a-zA-Z0-9_.+-][email protected][a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$") ( इस उत्तर से लिया गया), जोएल 1840 बाइट्स के कुल पदचिह्न की रिपोर्ट करता है, जिनमें से केवल 72 ही पैटर्न उदाहरण हैं।

java.util.regex.Pattern instance footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1       112       112   [C
         3       272       816   [Z
         1        24        24   java.lang.String
         1        72        72   java.util.regex.Pattern
         9        24       216   java.util.regex.Pattern$1
        13        24       312   java.util.regex.Pattern$5
         1        16        16   java.util.regex.Pattern$Begin
         3        24        72   java.util.regex.Pattern$BitClass
         3        32        96   java.util.regex.Pattern$Curly
         1        24        24   java.util.regex.Pattern$Dollar
         1        16        16   java.util.regex.Pattern$LastNode
         1        16        16   java.util.regex.Pattern$Node
         2        24        48   java.util.regex.Pattern$Single
        40                1840   (total)

यदि आप इसके बजाय GraphLayout.parseInstance(obj).toPrintable() उपयोग करते हैं, तो GraphLayout.parseInstance(obj).toPrintable() आपको प्रत्येक संदर्भित ऑब्जेक्ट के फ़ील्ड GraphLayout.parseInstance(obj).toPrintable() का पता, आकार, प्रकार, मान और पथ बताएगा, हालांकि आमतौर पर उपयोगी होने के लिए बहुत अधिक जानकारी होती है। चल रहे पैटर्न उदाहरण के लिए, आपको निम्न प्राप्त हो सकता है। (पते के बीच पता शायद बदल जाएगा।)

java.util.regex.Pattern object externals:
          ADDRESS       SIZE TYPE                             PATH                           VALUE
         d5e5f290         16 java.util.regex.Pattern$Node     .root.next.atom.next           (object)
         d5e5f2a0        120 (something else)                 (somewhere else)               (something else)
         d5e5f318         16 java.util.regex.Pattern$LastNode .root.next.next.next.next.next.next.next (object)
         d5e5f328      21664 (something else)                 (somewhere else)               (something else)
         d5e647c8         24 java.lang.String                 .pattern                       (object)
         d5e647e0        112 [C                               .pattern.value                 [^, [, a, -, z, A, -, Z, 0, -, 9, _, ., +, -, ], +, @, [, a, -, z, A, -, Z, 0, -, 9, -, ], +, \, ., [, a, -, z, A, -, Z, 0, -, 9, -, ., ], +, $]
         d5e64850        448 (something else)                 (somewhere else)               (something else)
         d5e64a10         72 java.util.regex.Pattern                                         (object)
         d5e64a58        416 (something else)                 (somewhere else)               (something else)
         d5e64bf8         16 java.util.regex.Pattern$Begin    .root                          (object)
         d5e64c08         24 java.util.regex.Pattern$BitClass .root.next.atom.val$rhs        (object)
         d5e64c20        272 [Z                               .root.next.atom.val$rhs.bits   [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
         d5e64d30         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64d48         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs.val$rhs (object)
         d5e64d60         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64d78         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$rhs (object)
         d5e64d90         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64da8         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs (object)
         d5e64dc0         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs (object)
         d5e64dd8         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs        (object)
         d5e64df0         24 java.util.regex.Pattern$5        .root.next.atom                (object)
         d5e64e08         32 java.util.regex.Pattern$Curly    .root.next                     (object)
         d5e64e28         24 java.util.regex.Pattern$Single   .root.next.next                (object)
         d5e64e40         24 java.util.regex.Pattern$BitClass .root.next.next.next.atom.val$rhs (object)
         d5e64e58        272 [Z                               .root.next.next.next.atom.val$rhs.bits [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
         d5e64f68         24 java.util.regex.Pattern$1        .root.next.next.next.atom.val$lhs.val$lhs.val$lhs (object)
         d5e64f80         24 java.util.regex.Pattern$1        .root.next.next.next.atom.val$lhs.val$lhs.val$rhs (object)
         d5e64f98         24 java.util.regex.Pattern$5        .root.next.next.next.atom.val$lhs.val$lhs (object)
         d5e64fb0         24 java.util.regex.Pattern$1        .root.next.next.next.atom.val$lhs.val$rhs (object)
         d5e64fc8         24 java.util.regex.Pattern$5        .root.next.next.next.atom.val$lhs (object)
         d5e64fe0         24 java.util.regex.Pattern$5        .root.next.next.next.atom      (object)
         d5e64ff8         32 java.util.regex.Pattern$Curly    .root.next.next.next           (object)
         d5e65018         24 java.util.regex.Pattern$Single   .root.next.next.next.next      (object)
         d5e65030         24 java.util.regex.Pattern$BitClass .root.next.next.next.next.next.atom.val$rhs (object)
         d5e65048        272 [Z                               .root.next.next.next.next.next.atom.val$rhs.bits [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
         d5e65158         24 java.util.regex.Pattern$1        .root.next.next.next.next.next.atom.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e65170         24 java.util.regex.Pattern$1        .root.next.next.next.next.next.atom.val$lhs.val$lhs.val$lhs.val$rhs (object)
         d5e65188         24 java.util.regex.Pattern$5        .root.next.next.next.next.next.atom.val$lhs.val$lhs.val$lhs (object)
         d5e651a0         24 java.util.regex.Pattern$1        .root.next.next.next.next.next.atom.val$lhs.val$lhs.val$rhs (object)
         d5e651b8         24 java.util.regex.Pattern$5        .root.next.next.next.next.next.atom.val$lhs.val$lhs (object)
         d5e651d0         24 java.util.regex.Pattern$5        .root.next.next.next.next.next.atom.val$lhs (object)
         d5e651e8         24 java.util.regex.Pattern$5        .root.next.next.next.next.next.atom (object)
         d5e65200         32 java.util.regex.Pattern$Curly    .root.next.next.next.next.next (object)
         d5e65220        120 (something else)                 (somewhere else)               (something else)
         d5e65298         24 java.util.regex.Pattern$Dollar   .root.next.next.next.next.next.next (object)

"(कुछ और)" प्रविष्टियां ढेर में अन्य वस्तुओं का वर्णन करती हैं जो इस ऑब्जेक्ट ग्राफ़ का हिस्सा नहीं हैं

सबसे अच्छा जोल दस्तावेज जोल भंडार में जोल नमूने है। नमूने सामान्य जोल परिचालन का प्रदर्शन करते हैं और दिखाते हैं कि आप वीएम और कचरा कलेक्टर आंतरिक का विश्लेषण करने के लिए जोल का उपयोग कैसे कर सकते हैं।


आपको इसे किसी टूल के साथ मापना होगा, या इसे हाथ से अनुमानित करना होगा, और यह आपके द्वारा उपयोग किए जा रहे JVM पर निर्भर करता है।

प्रति वस्तु कुछ निश्चित ओवरहेड है। यह जेवीएम-विशिष्ट है, लेकिन मैं आमतौर पर 40 बाइट अनुमान लगाता हूं। फिर आपको कक्षा के सदस्यों को देखना होगा। ऑब्जेक्ट संदर्भ 32-बिट (64-बिट) JVM में 4 (8) बाइट्स हैं। आदिम प्रकार हैं:

  • बूलियन और बाइट: 1 बाइट
  • चार और छोटा: 2 बाइट्स
  • int और float: 4 बाइट्स
  • लंबा और डबल: 8 बाइट्स

Arrays एक ही नियम का पालन करें; यानी, यह एक ऑब्जेक्ट रेफरेंस है जिससे आपकी ऑब्जेक्ट में 4 (या 8) बाइट्स लगते हैं, और फिर इसकी लंबाई उसके तत्व के आकार से गुणा हो जाती है।

Runtime.freeMemory() को कॉल के साथ प्रोग्रामेटिक रूप से करने की कोशिश कर रहा है, कचरा कलेक्टर आदि के लिए असीमित कॉल की वजह से आपको बहुत सटीकता नहीं मिलती है। एक्सचुनप्रोफ या अन्य टूल्स के साथ ढेर को प्रोफाइल करना आपको सबसे सटीक परिणाम देगा।


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

कक्षा के दृश्यों के पीछे चल रही चीजों के कारण यह हमेशा मूल सी कार्यान्वयन से कुछ हद तक कम सटीक होने वाला है लेकिन यह एक अच्छा संकेतक होना चाहिए।

वैकल्पिक रूप से एक SourceForge प्रोजेक्ट को उचित रूप से sizeof जाता है जो एक आकार () कार्यान्वयन के साथ Java5 लाइब्रेरी प्रदान करता है।

पीएस क्रमबद्धता दृष्टिकोण का उपयोग न करें, धारावाहिक वस्तु के आकार और लाइव होने पर उपभोग की मात्रा के बीच कोई सहसंबंध नहीं है।


जब मैंने ट्विटर पर काम किया, तो मैंने गहरे ऑब्जेक्ट आकार की गणना करने के लिए उपयोगिता लिखी। यह अलग-अलग मेमोरी मॉडल (32-बिट, संपीड़ित ओप्स, 64-बिट), पैडिंग, सबक्लास पैडिंग को ध्यान में रखता है, परिपत्र डेटा संरचनाओं और सरणी पर सही ढंग से काम करता है। आप इसे सिर्फ एक .java फ़ाइल संकलित कर सकते हैं; इसकी कोई बाहरी निर्भरता नहीं है:

https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/objectsize/ObjectSizeCalculator.java


मैंने गलती से एक जावा क्लास "jdk.nashorn.internal.ir.debug.ObjectSizeCalculator" पाया, पहले से ही जेडीके में, जो उपयोग करना आसान है और किसी ऑब्जेक्ट के आकार को निर्धारित करने के लिए काफी उपयोगी लगता है।

System.out.println(ObjectSizeCalculator.getObjectSize(new gnu.trove.map.hash.TObjectIntHashMap<String>(12000, 0.6f, -1)));
System.out.println(ObjectSizeCalculator.getObjectSize(new HashMap<String, Integer>(100000)));
System.out.println(ObjectSizeCalculator.getObjectSize(3));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[]{1, 2, 3, 4, 5, 6, 7 }));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[100]));

परिणाम:

164192
48
16
48
416

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

तो एकमात्र सही तरीका है कि एक अच्छा प्रोफाइलर (मैं आपकीकिट का उपयोग करता हूं ) के साथ, JVM से पूछना है, जो शायद आप नहीं चाहते हैं।

हालांकि, ऊपर दिए गए विवरण से ऐसा लगता है कि प्रत्येक पंक्ति स्वयं निहित होगी, और कोई बड़ा निर्भरता पेड़ नहीं होगा, इसलिए सीरियलाइजेशन विधि शायद अधिकांश जेवीएम पर एक अच्छा अनुमान होगा। ऐसा करने का सबसे आसान तरीका निम्नानुसार है:

 Serializable ser;
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(baos);
 oos.writeObject(ser);
 oos.close();
 return baos.size();

याद रखें कि यदि आपके पास सामान्य संदर्भ वाले ऑब्जेक्ट हैं तो यह सही परिणाम नहीं देगा, और क्रमबद्धता का आकार हमेशा स्मृति में आकार से मेल नहीं खाएगा, लेकिन यह एक अच्छा अनुमान है। यदि आप ByteArrayOutputStream आकार को समझदार मान में प्रारंभ करते हैं तो कोड थोड़ा अधिक कुशल होगा।


मेमोरी मेजर टूल (पहले Google कोड पर , अब गिटहब पर) भी है, जो वाणिज्यिक-अनुकूल अपाचे 2.0 लाइसेंस के तहत सरल और प्रकाशित है, जैसा कि एक समान प्रश्न में चर्चा की गई है।

यदि आप मेमोरी बाइट खपत को मापना चाहते हैं, तो जावा जावा दुभाषिया को भी कमांड लाइन तर्क की आवश्यकता होती है, लेकिन अन्यथा कम से कम परिदृश्य में, ठीक से काम करने लगता है।


Here is a utility I made using some of the linked examples to handle 32-bit, 64-bit and 64-bit with compressed OOP. It uses sun.misc.Unsafe .

It uses Unsafe.addressSize() to get the size of a native pointer and Unsafe.arrayIndexScale( Object[].class ) for the size of a Java reference.

It uses the field offset of a known class to work out the base size of an object.

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Stack;
import sun.misc.Unsafe;

/** Usage: 
 * MemoryUtil.sizeOf( object )
 * MemoryUtil.deepSizeOf( object )
 * MemoryUtil.ADDRESS_MODE
 */
public class MemoryUtil
{
    private MemoryUtil()
    {
    }

    public static enum AddressMode
    {
        /** Unknown address mode. Size calculations may be unreliable. */
        UNKNOWN,
        /** 32-bit address mode using 32-bit references. */
        MEM_32BIT,
        /** 64-bit address mode using 64-bit references. */
        MEM_64BIT,
        /** 64-bit address mode using 32-bit compressed references. */
        MEM_64BIT_COMPRESSED_OOPS
    }

    /** The detected runtime address mode. */
    public static final AddressMode ADDRESS_MODE;

    private static final Unsafe UNSAFE;

    private static final long ADDRESS_SIZE; // The size in bytes of a native pointer: 4 for 32 bit, 8 for 64 bit
    private static final long REFERENCE_SIZE; // The size of a Java reference: 4 for 32 bit, 4 for 64 bit compressed oops, 8 for 64 bit
    private static final long OBJECT_BASE_SIZE; // The minimum size of an Object: 8 for 32 bit, 12 for 64 bit compressed oops, 16 for 64 bit
    private static final long OBJECT_ALIGNMENT = 8;

    /** Use the offset of a known field to determine the minimum size of an object. */
    private static final Object HELPER_OBJECT = new Object() { byte b; };


    static
    {
        try
        {
            // Use reflection to get a reference to the 'Unsafe' object.
            Field f = Unsafe.class.getDeclaredField( "theUnsafe" );
            f.setAccessible( true );
            UNSAFE = (Unsafe) f.get( null );

            OBJECT_BASE_SIZE = UNSAFE.objectFieldOffset( HELPER_OBJECT.getClass().getDeclaredField( "b" ) );

            ADDRESS_SIZE = UNSAFE.addressSize();
            REFERENCE_SIZE = UNSAFE.arrayIndexScale( Object[].class );

            if( ADDRESS_SIZE == 4 )
            {
                ADDRESS_MODE = AddressMode.MEM_32BIT;
            }
            else if( ADDRESS_SIZE == 8 && REFERENCE_SIZE == 8 )
            {
                ADDRESS_MODE = AddressMode.MEM_64BIT;
            }
            else if( ADDRESS_SIZE == 8 && REFERENCE_SIZE == 4 )
            {
                ADDRESS_MODE = AddressMode.MEM_64BIT_COMPRESSED_OOPS;
            }
            else
            {
                ADDRESS_MODE = AddressMode.UNKNOWN;
            }
        }
        catch( Exception e )
        {
            throw new Error( e );
        }
    }


    /** Return the size of the object excluding any referenced objects. */
    public static long shallowSizeOf( final Object object )
    {
        Class<?> objectClass = object.getClass();
        if( objectClass.isArray() )
        {
            // Array size is base offset + length * element size
            long size = UNSAFE.arrayBaseOffset( objectClass )
                    + UNSAFE.arrayIndexScale( objectClass ) * Array.getLength( object );
            return padSize( size );
        }
        else
        {
            // Object size is the largest field offset padded out to 8 bytes
            long size = OBJECT_BASE_SIZE;
            do
            {
                for( Field field : objectClass.getDeclaredFields() )
                {
                    if( (field.getModifiers() & Modifier.STATIC) == 0 )
                    {
                        long offset = UNSAFE.objectFieldOffset( field );
                        if( offset >= size )
                        {
                            size = offset + 1; // Field size is between 1 and PAD_SIZE bytes. Padding will round up to padding size.
                        }
                    }
                }
                objectClass = objectClass.getSuperclass();
            }
            while( objectClass != null );

            return padSize( size );
        }
    }


    private static final long padSize( final long size )
    {
        return (size + (OBJECT_ALIGNMENT - 1)) & ~(OBJECT_ALIGNMENT - 1);
    }


    /** Return the size of the object including any referenced objects. */
    public static long deepSizeOf( final Object object )
    {
        IdentityHashMap<Object,Object> visited = new IdentityHashMap<Object,Object>();
        Stack<Object> stack = new Stack<Object>();
        if( object != null ) stack.push( object );

        long size = 0;
        while( !stack.isEmpty() )
        {
            size += internalSizeOf( stack.pop(), stack, visited );
        }
        return size;
    }


    private static long internalSizeOf( final Object object, final Stack<Object> stack, final IdentityHashMap<Object,Object> visited )
    {
        // Scan for object references and add to stack
        Class<?> c = object.getClass();
        if( c.isArray() && !c.getComponentType().isPrimitive() )
        {
            // Add unseen array elements to stack
            for( int i = Array.getLength( object ) - 1; i >= 0; i-- )
            {
                Object val = Array.get( object, i );
                if( val != null && visited.put( val, val ) == null )
                {
                    stack.add( val );
                }
            }
        }
        else
        {
            // Add unseen object references to the stack
            for( ; c != null; c = c.getSuperclass() )
            {
                for( Field field : c.getDeclaredFields() )
                {
                    if( (field.getModifiers() & Modifier.STATIC) == 0 
                            && !field.getType().isPrimitive() )
                    {
                        field.setAccessible( true );
                        try
                        {
                            Object val = field.get( object );
                            if( val != null && visited.put( val, val ) == null )
                            {
                                stack.add( val );
                            }
                        }
                        catch( IllegalArgumentException e )
                        {
                            throw new RuntimeException( e );
                        }
                        catch( IllegalAccessException e )
                        {
                            throw new RuntimeException( e );
                        }
                    }
                }
            }
        }

        return shallowSizeOf( object );
    }
}

I wrote a quick test once to estimate on the fly:

public class Test1 {

    // non-static nested
    class Nested { }

    // static nested
    static class StaticNested { }

    static long getFreeMemory () {
        // waits for free memory measurement to stabilize
        long init = Runtime.getRuntime().freeMemory(), init2;
        int count = 0;
        do {
            System.out.println("waiting..." + init);
            System.gc();
            try { Thread.sleep(250); } catch (Exception x) { }
            init2 = init;
            init = Runtime.getRuntime().freeMemory();
            if (init == init2) ++ count; else count = 0;
        } while (count < 5);
        System.out.println("ok..." + init);
        return init;
    }

    Test1 () throws InterruptedException {

        Object[] s = new Object[10000];
        Object[] n = new Object[10000];
        Object[] t = new Object[10000];

        long init = getFreeMemory();

        //for (int j = 0; j < 10000; ++ j)
        //    s[j] = new Separate();

        long afters = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            n[j] = new Nested();

        long aftersn = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            t[j] = new StaticNested();

        long aftersnt = getFreeMemory();

        System.out.println("separate:      " + -(afters - init) + " each=" + -(afters - init) / 10000);
        System.out.println("nested:        " + -(aftersn - afters) + " each=" + -(aftersn - afters) / 10000);
        System.out.println("static nested: " + -(aftersnt - aftersn) + " each=" + -(aftersnt - aftersn) / 10000);

    }

    public static void main (String[] args) throws InterruptedException {
        new Test1();
    }

}

General concept is allocate objects and measure change in free heap space. The key being getFreeMemory() , which requests GC runs and waits for the reported free heap size to stabilize . The output of the above is:

nested:        160000 each=16
static nested: 160000 each=16

Which is what we expect, given alignment behavior and possible heap block header overhead.

The instrumentation method detailed in the accepted answer here the most accurate. The method I described is accurate but only under controlled conditions where no other threads are creating/discarding objects.


Just use java visual VM.

It has everything you need to profile and debug memory problems.

It also has a OQL (Object Query Language) console which allows you to do many useful things, one of which being sizeof(o)


The below code can help you surely.

`object.toString().getBytes("UTF-8").length`

returns size in bytes

I checked it with my JSONArray object by writing it to a file. It is giving object size.


There isn't a method call, if that's what you're asking for. With a little research, I suppose you could write your own. A particular instance has a fixed sized derived from the number of references and primitive values plus instance bookkeeping data. You would simply walk the object graph. The less varied the row types, the easier.

If that's too slow or just more trouble than it's worth, there's always good old-fashioned row counting rule-of-thumbs.


Without having to mess with instrumentation and so on, and if you don't need to know the byte-exact size of an object, you could go with the following approach:

System.gc();
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

do your job here

System.gc();
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

This way you read the used memory before and after, and calling the GC just before getting the used memory you lower the "noise" almost to 0.

For a more reliable result you can run your job n times, and then divide the used memory by n, obtaining how much memory one run takes. Even more, you can run the whole thing more times and make an average.


You could generate a heap dump (with jmap, for example) and then analyze the output to find object sizes. This is an offline solution, but you can examine shallow and deep sizes, etc.








memory