Calculer la taille de L'objet en Java [dupliquer]

cette question a déjà une réponse ici:

  • en Java, Quelle est la meilleure façon de déterminer la taille d'un objet? 24 réponses

je veux enregistrer combien de mémoire (en octets, j'espère) un objet prend pour un projet (je compare les tailles des structures de données) et il semble comme S'il n'y avait pas de méthode pour faire ça en Java. Il est supposé que C / C++ a la méthode sizeOf() , mais celle-ci n'existe pas en Java. J'ai essayé d'enregistrer la mémoire libre dans le JVM avec Runtime.getRuntime().freeMemory() avant et après la création de l'objet et puis d'enregistrer la différence, mais il ne donnerait que 0 ou 131304, et rien entre les deux, quel que soit le nombre d'éléments dans la structure. De l'aide s'il vous plaît!

122
demandé sur posdef 2012-02-21 01:36:32

4 réponses

vous pouvez utiliser le paquet java.lang.instrumentation :

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

il a une méthode qui peut être utilisé pour obtenir la mise en œuvre spécifique approximation de la taille de l'objet, ainsi que les frais généraux associés à l'objet.

la réponse que Sergey A liée a un grand exemple, que je vais reposer ici, mais vous devriez déjà avoir regardé à partir de son commentaire:

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

Use getObjectSize:

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

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

Source:

en Java, Quelle est la meilleure façon de déterminer la taille d'un objet?

74
répondu Hunter McMillen 2018-05-30 11:01:46

regardez https://github.com/DimitrisAndreou/memory-measurer Guava l'utilise en interne, et Objectgraphmesureur est particulièrement simple à utiliser hors de la boîte, sans aucun argument de ligne de commande spéciale. 

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));
  }
}
68
répondu Louis Wasserman 2017-02-17 18:24:13

la classe java.lang.instrument.Instrumentation fournit une bonne façon d'obtenir la taille D'un objet Java, mais elle vous demande de définir un premain et d'exécuter votre programme avec un agent java. C'est très ennuyeux quand vous n'avez pas besoin d'un agent et puis vous devez fournir un agent bidon pour votre application.

J'ai donc obtenu une solution alternative en utilisant la classe Unsafe de la sun.misc . Ainsi, en considérant l'alignement de tas d'objets selon l'architecture du processeur et en calculant le décalage de champ maximum, vous pouvez mesurer la taille d'un objet Java. Dans l'exemple ci-dessous, j'utilise une classe auxiliaire UtilUnsafe pour obtenir une référence à la sun.misc.Unsafe objet.

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
répondu Miguel Gamboa 2012-05-14 16:32:29

une recherche google de " Java sizeof "a abouti à un bel article sur Java sizeof sur javaworld. En fait, une lecture intéressante.

pour répondre à votre question, il n'y a pas D'équivalent Java de" sizeof ()", mais l'article décrit quelques façons d'obtenir la taille de byte de vos classes instanciées.

2
répondu John 2012-02-20 21:45:04