Calcular el tamaño del objeto en Java [duplicado]
Quiero registrar cuánta memoria (en bytes, con suerte) ocupa un objeto para un proyecto (estoy comparando tamaños de estructuras de datos) y parece que no existe ningún método para hacerlo en Java. Supuestamente, C/C++ tiene sizeOf()
un método, pero este no existe en Java. Intenté registrar la memoria libre en la JVM Runtime.getRuntime().freeMemory()
antes y después de crear el objeto y luego registrar la diferencia, pero solo daba 0 o 131304, y nada intermedio, independientemente de la cantidad de elementos en la estructura. ¡Ayuda por favor!
Puedes usar el java.lang.instrumentation
paquete.
Tiene un método que se puede utilizar para obtener la aproximación específica de la implementación del tamaño del objeto, así como la sobrecarga asociada con el objeto.
La respuesta que Sergey vinculó tiene un gran ejemplo, que volveré a publicar aquí, pero ya deberías haberlo visto en su comentario:
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);
}
}
Usar getObjectSize
:
public class C {
private int x;
private int y;
public static void main(String [] args) {
System.out.println(ObjectSizeFetcher.getObjectSize(new C()));
}
}
Fuente
Busque en https://github.com/DimitrisAndreou/memory-measurer .
Guava lo usa internamente y ObjectGraphMeasurer
es especialmente sencillo de usar desde el primer momento, sin ningún argumento especial de línea de comandos.
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));
}
}
La java.lang.instrument.Instrumentation
clase proporciona una buena manera de obtener el tamaño de un objeto Java, pero requiere que definas premain
y ejecutes tu programa con un agente Java. Esto es muy aburrido cuando no necesitas ningún agente y luego tienes que proporcionar un agente Jar ficticio a tu aplicación.
Entonces obtuve una solución alternativa usando la Unsafe
clase de sun.misc
. Entonces, considerando la alineación del montón de objetos de acuerdo con la arquitectura del procesador y calculando el desplazamiento máximo del campo, puede medir el tamaño de un objeto Java. En el siguiente ejemplo utilizo una clase auxiliar UtilUnsafe
para obtener una referencia al sun.misc.Unsafe
objeto.
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() { }
}