2012-02-20 16 views
106

मैं रिकॉर्ड करना चाहता हूं कि एक वस्तु के लिए एक वस्तु (बाइट्स, उम्मीद है कि) एक वस्तु के लिए कितनी मेमोरी लेती है (मैं डेटा संरचनाओं के आकार की तुलना कर रहा हूं) और ऐसा लगता है कि ऐसा करने के लिए कोई तरीका नहीं है जावा में माना जाता है कि, सी/सी ++ में sizeOf() विधि है, लेकिन यह जावा में कोई भी नहीं है। मैंने ऑब्जेक्ट बनाने से पहले और बाद में Runtime.getRuntime().freeMemory() के साथ JVM में मुफ्त मेमोरी रिकॉर्ड करने का प्रयास किया और फिर अंतर रिकॉर्ड किया, लेकिन यह केवल 0 या 131304, और संरचना में तत्वों की संख्या के बावजूद, बीच में कुछ भी नहीं देगा। कृपया मदद करें!जावा में ऑब्जेक्ट के आकार की गणना

http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html

यह एक विधि है कि वस्तु के आकार के कार्यान्वयन विशिष्ट सन्निकटन है, साथ ही भूमि के ऊपर वस्तु के साथ जुड़े पाने के लिए इस्तेमाल किया जा सकता है:

+4

http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object –

+0

आप कर सकते हैं कुल मेमरी() और फिर फ्रीमेमरी() को आज़माएं और इसके बजाय उन घटाना। – Matt

+2

मैं आपको जेबेलिस जेएमएम पर एक नज़र डालने की सलाह देता हूं। (https://github.com/jbellis/jamm) यह ऊपर वर्णित उपकरण एजेंट पर निर्भर करता है लेकिन पूरे ऑब्जेक्ट-ग्राफ़ के पदचिह्न को गहराई से मापने के लिए कुछ हंसमुख उपयोगिताओं को समाहित करता है। मेरे लिए सरल और बहुत अच्छा लग रहा है। – Claudio

उत्तर

68

आप java.lang.instrumentation पैकेज का उपयोग कर सकते हैं।

जवाब यह है कि सेर्गेई जुड़ा हुआ एक महान उदाहरण है, जो मैं यहाँ repost हूँ है, लेकिन आप पहले से ही होना चाहिए उसकी टिप्पणी से देखा:

import java.lang.instrument.Instrumentation; 

public class ObjectSizeFetcher { 
    private static Instrumentation instrumentation; 

    public static void premain(String args, Instrumentation inst) { 
     instrumentation = inst; 
    } 

    public static long getObjectSize(Object o) { 
     return instrumentation.getObjectSize(o); 
    } 
} 

उपयोग getObjectSize:

public class C { 
    private int x; 
    private int y; 

    public static void main(String [] args) { 
     System.out.println(ObjectSizeFetcher.getObjectSize(new C())); 
    } 
} 

स्रोत

In Java, what is the best way to determine the size of an object?

+1

कहते हैं "इंस्ट्रुमेंटेशन इंटरफ़ेस के उदाहरण को एक्सेस करने का एकमात्र तरीका जेवीएम को ऐसे तरीके से लॉन्च किया जा सकता है जो एजेंट वर्ग को इंगित करता है - पैकेज विनिर्देश देखें। इंस्ट्रुमेंटेशन इंस्टेंस एजेंट एजेंट की पहली विधि को पास कर दिया जाता है। एक एजेंट इंस्ट्रुमेंटेशन इंस्टेंस प्राप्त करता है, एजेंट किसी भी समय इंस्टेंस पर विधियों को कॉल कर सकता है। "<- मैं यह कैसे कर सकता हूं (ग्रहण में)? –

+0

मुझे यह निर्दिष्ट नहीं करना है कि JVM कैसे लॉन्च करता है? मैंने कोशिश की और यह मुझे NullPointerException –

+1

दे रहा है जो आपने कोशिश की थी उसके ऊपर अपनी पोस्ट संपादित करें। –

1

एक गूगल: उदाहरण के लिए "जावा आकार" की खोज के परिणामस्वरूप javaworld पर Java sizeof के बारे में एक अच्छा लेख हुआ। असल में, एक दिलचस्प पढ़ा।

अपने प्रश्न का उत्तर देने के लिए, "sizeof()" के बराबर जावा नहीं है, लेकिन लेख आपके तत्काल वर्गों के बाइट आकार के बारे में कुछ तरीकों का वर्णन करता है।

65

https://github.com/DimitrisAndreou/memory-measurer में देखें 0 अमरूद इसे आंतरिक रूप से उपयोग करता है, और ऑब्जेक्टग्राफमेजर विशेष रूप से बिना किसी विशेष कमांड लाइन तर्क के आउट ऑफ़ द बॉक्स का उपयोग करने के लिए सीधा है।  

import objectexplorer.ObjectGraphMeasurer; 

public class Measurer { 

    public static void main(String[] args) { 
    Set<Integer> hashset = new HashSet<Integer>(); 
    Random random = new Random(); 
    int n = 10000; 
    for (int i = 1; i <= n; i++) { 
     hashset.add(random.nextInt()); 
    } 
    System.out.println(ObjectGraphMeasurer.measure(hashset)); 
    } 
} 
+0

यह बहुत उपयोगी था। यहां तक ​​कि दूसरा इसे काम करने के लिए बहुत आसान था। क्या आपने पहले इसका इस्तेमाल किया है? – Venki

+1

मैंने पहले स्मृति-मापक का उपयोग किया है, हां। (मैं अमरूद में योगदान देता हूं, और मैंने उल्लेख किया कि हम इसे आंतरिक रूप से उपयोग करते हैं।)) –

+0

तत्काल प्रतिक्रिया। यही कारण है कि मैं एसओ प्यार करता हूँ। अनेक अनेक धन्यवाद। मैं स्मृति गतिविधि को मापने के लिए इसका उपयोग करने की कोशिश कर रहा हूं। यह बहुत आसान में आया है। – Venki

14

java.lang.instrument.Instrumentation वर्ग एक जावा वस्तु के आकार पाने के लिए एक अच्छा तरीका प्रदान करता है, लेकिन यह एक premain को परिभाषित करने और एक जावा एजेंट के साथ अपने कार्यक्रम चलाने की आवश्यकता है। यह बहुत उबाऊ है जब आपको किसी एजेंट की आवश्यकता नहीं होती है और फिर आपको अपने आवेदन के लिए डमी जार एजेंट प्रदान करना होगा।

तो मुझे sun.misc से Unsafe कक्षा का उपयोग करके एक वैकल्पिक समाधान मिला। इसलिए, प्रोसेसर आर्किटेक्चर के अनुसार ऑब्जेक्ट हेप संरेखण पर विचार करना और अधिकतम फ़ील्ड ऑफसेट की गणना करना, आप जावा ऑब्जेक्ट के आकार को माप सकते हैं। नीचे दिए गए उदाहरण में sun.misc.Unsafe ऑब्जेक्ट का संदर्भ प्राप्त करने के लिए मैं एक सहायक वर्ग UtilUnsafe का उपयोग करता हूं।

private static final int NR_BITS = Integer.valueOf(System.getProperty("sun.arch.data.model")); 
private static final int BYTE = 8; 
private static final int WORD = NR_BITS/BYTE; 
private static final int MIN_SIZE = 16; 

public static int sizeOf(Class src){ 
    // 
    // Get the instance fields of src class 
    // 
    List<Field> instanceFields = new LinkedList<Field>(); 
    do{ 
     if(src == Object.class) return MIN_SIZE; 
     for (Field f : src.getDeclaredFields()) { 
      if((f.getModifiers() & Modifier.STATIC) == 0){ 
       instanceFields.add(f); 
      } 
     } 
     src = src.getSuperclass(); 
    }while(instanceFields.isEmpty()); 
    // 
    // Get the field with the maximum offset 
    // 
    long maxOffset = 0; 
    for (Field f : instanceFields) { 
     long offset = UtilUnsafe.UNSAFE.objectFieldOffset(f); 
     if(offset > maxOffset) maxOffset = offset; 
    } 
    return (((int)maxOffset/WORD) + 1)*WORD; 
} 
class UtilUnsafe { 
    public static final sun.misc.Unsafe UNSAFE; 

    static { 
     Object theUnsafe = null; 
     Exception exception = null; 
     try { 
      Class<?> uc = Class.forName("sun.misc.Unsafe"); 
      Field f = uc.getDeclaredField("theUnsafe"); 
      f.setAccessible(true); 
      theUnsafe = f.get(uc); 
     } catch (Exception e) { exception = e; } 
     UNSAFE = (sun.misc.Unsafe) theUnsafe; 
     if (UNSAFE == null) throw new Error("Could not obtain access to sun.misc.Unsafe", exception); 
    } 
    private UtilUnsafe() { } 
} 
+0

मैं इस बारे में निश्चित नहीं हूँ: ((int) maxOffset/वर्ड) +1) * वर्ड, लेकिन मैं इसे काम करता है लगता है के रूप में मैं यकीन है कि 64 बिट चर कभी नहीं एक 64-बिट में एक 8 बाइट सीमा crosssing कर रहे हैं हूँ वी एम। अच्छा कोड अन्यथा, हालांकि आप निश्चित रूप से पूरे मानचित्र बनाने के प्रयास से छुटकारा पा सकते हैं। मैंने अपना खुद का संस्करण बनाया जो ऑब्जेक्ट एरे को यहां भी संभालता है: http://tinybrain.de/1011517 (अभी भी आदिम सरणी जोड़ने की आवश्यकता होगी)। –

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