2012-01-08 25 views
10

私は、Javaオブジェクトのサイズを取得する簡単な方法を知りたいですか?また、とにかくC++のsizeof演算子のようなクラスのサイズを取得するには?Javaオブジェクトのサイズを取得する簡単な方法はありますか?

+0

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

+0

あなたがより多くのことができます特定。あなたはJavaオブジェクトが使用しているメモリのサイズについて話していますか? –

+0

を参照してください。http://stackoverflow.com/questions/757300/programatically-calculate-memory-occupied-by-a-java-object-including-objects-it – user371320

答えて

6

Instrumentationインターフェイスには、getObjectSize()メソッドがあります。

ただし、コンポーネントのサブオブジェクトではなく、オブジェクト自体のサイズのみが表示されます。たとえば、すべてのStringオブジェクトが同じサイズであることがわかります。

もう1つの問題は、オブジェクトのサイズが実際に自発的に変更できることです。たとえば、オブジェクトのアイデンティティハッシュコードを取得し、それがGCサイクルで存続する場合、アイデンティティハッシュコード値を格納するために、そのサイズが(少なくとも)4バイト増加します。


「オブジェクト」の大きさを求める問題は、一般的なユーティリティクラス/メソッドは、任意のオブジェクトの抽象化の境界がどこにあるか確実に知ることが不可能であるということです。 Stringクラスほどシンプルなものにも問題があります。 (DOのJava 6のsubstring(...)を使用して作成されたStringオブジェクトを考えてみましょうあなたでしthisの一部、または元の文字列の一部、またはその両方?これは、各オブジェクトのサイズは何を意味するのか?などchar[] valueオブジェクト)

このように、net.sourceforge.sizeofのようなものでは、スペース使用量を完全に正確に計算することはできません。

0

あなたのプログラムが別のターミナルウィンドウを取得し、実行し、実行している間:

jmap -histo <process id of the java instance you want to debug> 

出力ではクラスによって、オブジェクトのインスタンスの数と合計サイズを与えます。たとえば、3 72 java.util.Dateは、それぞれ24バイトを取るメモリ内に3つのDateオブジェクトがあることを意味します。関連する部分があまりにも速くスクロールする場合は、出力をファイルなどにパイプする必要があります。

あるいは、(多くの)詳細については、以下を実行します。

jmap -dump:format=b,file=heap.bin <processid> 
jhat heap.bin 

その後http://localhost:7000を開きます。ブラウザのヒープ上のオブジェクトを参照することができます。

さらに詳しい情報:

http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jhat.html

私は、オブジェクトが12バイトであっても、日/オラクルJVM上で、それはいつもの方法により8に切り上げます考えて、それがかかります16をメモリに格納します。

3

Unsafeクラスを使用すると、オフセットを取得できます。したがって、オブジェクトがプロセッサのアーキテクチャに従ってアライメントをヒープし、最大フィールドオフセットを計算することを考慮すると、Javaオブジェクトのサイズを測定できます。以下の例では、補助クラスUtilUnsafeを使用してsun.misc.Unsafeオブジェクトへの参照を取得します。

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

特定のクラスのオブジェクトは固定サイズのメモリブロックであるため、オブジェクトサイズを取得することは間違いありません。私はオブジェクトの保持されたサイズを計算するために次のコードを書いた。また、C++の 'sizeof'のようなメソッドを提供します。それはすぐに実行でき、何にも依存しません。コピーして試してみてください!

public class ObjectSizer { 

    public static final Unsafe us = getUnsafe(); 

    public static boolean useCompressedOops = true; 

    public static int retainedSize(Object obj) { 
     return retainedSize(obj, new HashMap<Object, Object>()); 
    } 

    private static int retainedSize(Object obj, HashMap<Object, Object> calculated) { 
     try { 
      if (obj == null) 
       throw new NullPointerException(); 
      calculated.put(obj, obj); 
      Class<?> cls = obj.getClass(); 
      if (cls.isArray()) { 
       int arraysize = us.arrayBaseOffset(cls) + us.arrayIndexScale(cls) * Array.getLength(obj); 
       if (!cls.getComponentType().isPrimitive()) { 
        Object[] arr = (Object[]) obj; 
        for (Object comp : arr) { 
         if (comp != null && !isCalculated(calculated, comp)) 
          arraysize += retainedSize(comp, calculated); 
        } 
       } 
       return arraysize; 
      } else { 
       int objectsize = sizeof(cls); 
       for (Field f : getAllNonStaticFields(obj.getClass())) { 
        Class<?> fcls = f.getType(); 
        if (fcls.isPrimitive()) 
         continue; 
        f.setAccessible(true); 
        Object ref = f.get(obj); 
        if (ref != null && !isCalculated(calculated, ref)) { 
         int referentSize = retainedSize(ref, calculated); 
         objectsize += referentSize; 
        } 
       } 
       return objectsize; 
      } 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static int sizeof(Class<?> cls) { 

     if (cls == null) 
      throw new NullPointerException(); 

     if (cls.isArray()) 
      throw new IllegalArgumentException(); 

     if (cls.isPrimitive()) 
      return primsize(cls); 

     int lastOffset = Integer.MIN_VALUE; 
     Class<?> lastClass = null; 

     for (Field f : getAllNonStaticFields(cls)) { 
      if (Modifier.isStatic(f.getModifiers())) 
       continue; 

      int offset = (int) us.objectFieldOffset(f); 
      if (offset > lastOffset) { 
       lastOffset = offset; 
       lastClass = f.getClass(); 
      } 
     } 
     if (lastOffset > 0) 
      return modulo8(lastOffset + primsize(lastClass)); 
     else 
      return 16; 
    } 

    private static Field[] getAllNonStaticFields(Class<?> cls) { 
     if (cls == null) 
      throw new NullPointerException(); 

     List<Field> fieldList = new ArrayList<Field>(); 
     while (cls != Object.class) { 
      for (Field f : cls.getDeclaredFields()) { 
       if (!Modifier.isStatic(f.getModifiers())) 
        fieldList.add(f); 
      } 
      cls = cls.getSuperclass(); 
     } 
     Field[] fs = new Field[fieldList.size()]; 
     fieldList.toArray(fs); 
     return fs; 
    } 

    private static boolean isCalculated(HashMap<Object, Object> calculated, Object test) { 
     Object that = calculated.get(test); 
     return that != null && that == test; 
    } 

    private static int primsize(Class<?> cls) { 
     if (cls == byte.class) 
      return 1; 
     if (cls == boolean.class) 
      return 1; 
     if (cls == char.class) 
      return 2; 
     if (cls == short.class) 
      return 2; 
     if (cls == int.class) 
      return 4; 
     if (cls == float.class) 
      return 4; 
     if (cls == long.class) 
      return 8; 
     if (cls == double.class) 
      return 8; 
     else 
      return useCompressedOops ? 4 : 8; 
    } 

    private static int modulo8(int value) { 
     return (value & 0x7) > 0 ? (value & ~0x7) + 8 : value; 
    } 

    private static Unsafe getUnsafe() { 
     try { 
      Field f = Unsafe.class.getDeclaredField("theUnsafe"); 
      f.setAccessible(true); 
      return (Unsafe) f.get(Unsafe.class); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static void main(String[] args) { 
     System.out.println(retainedSize("Hello Leeeeeeeen")); 
    } 
} 
関連する問題