it-swarm.com.de

Berechnen Sie die Größe des Objekts in Java

Ich möchte aufzeichnen, wie viel Speicher (in Bytes, hoffentlich) ein Objekt für ein Projekt benötigt (ich vergleiche die Größe von Datenstrukturen), und es scheint, als gäbe es in Java keine Methode, um dies zu tun. Angeblich hat C/C++ die Methode sizeOf(), die in Java jedoch nicht vorhanden ist. Ich habe versucht, den freien Speicher in der JVM mit Runtime.getRuntime().freeMemory() vor und nach dem Erstellen des Objekts aufzuzeichnen und dann die Differenz aufzuzeichnen, aber es wurde nur 0 oder 131304 und nichts dazwischen angegeben, unabhängig von der Anzahl der Elemente in die Struktur. Hilfe bitte!

143
Tyler Petrochko

Du kannst den ... benutzen Java.lang.instrumentation Paket:

http://docs.Oracle.com/javase/7/docs/api/Java/lang/instrument/Instrumentation.html

Es verfügt über eine Methode, mit der die implementierungsspezifische Approximation der Objektgröße sowie des mit dem Objekt verbundenen Overheads ermittelt werden kann.

Die Antwort, die Sergey verlinkt hat, hat ein großartiges Beispiel, das ich hier erneut posten werde, aber Sie sollten sich bereits seinen Kommentar angesehen haben:

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);
    }
}

Verwenden Sie getObjectSize:

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

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

Quelle:

Wie lässt sich in Java die Größe eines Objekts am besten bestimmen?

82
Hunter McMillen

Schauen Sie in https://github.com/DimitrisAndreou/memory-measurer Guava verwendet es intern, und ObjectGraphMeasurer ist ohne spezielle Befehlszeilenargumente besonders einfach zu verwenden.

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));
  }
}
76
Louis Wasserman

Die Klasse Java.lang.instrument.Instrumentation Bietet eine gute Möglichkeit, die Größe eines Java -Objekts abzurufen. Sie müssen jedoch eine premain definieren und Ihr Programm mit einem Java Agent. Dies ist sehr langweilig, wenn Sie keinen Agenten benötigen und dann einen Dummy-Jar-Agenten für Ihre Anwendung bereitstellen müssen.

Also habe ich eine alternative Lösung mit der Klasse Unsafe aus Sun.misc. Wenn Sie also die Ausrichtung des Objekt-Heapspeichers gemäß der Prozessorarchitektur berücksichtigen und den maximalen Feldversatz berechnen, können Sie die Größe eines Java -Objekts messen. Im folgenden Beispiel verwende ich eine Hilfsklasse UtilUnsafe, um einen Verweis auf das Objekt Sun.misc.Unsafe Zu erhalten.

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() { }
}
16
Miguel Gamboa

Eine Google-Suche von "Java sizeof" ergab einen netten Artikel über Java sizeof auf javaworld. Eigentlich eine interessante Lektüre.

Um Ihre Frage zu beantworten, gibt es kein Java äquivalent zu "sizeof ()", aber der Artikel beschreibt einige Möglichkeiten, wie Sie die Bytegröße Ihrer instanziierten Klassen ermitteln können.

2
John