Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate size of Object in Java [duplicate]

People also ask

How do you find the size of an object in Java?

One way to get an estimate of an object's size in Java is to use getObjectSize(Object) method of the Instrumentation interface introduced in Java 5. As we could see in Javadoc documentation, the method provides “implementation-specific approximation” of the specified object's size.

How do you duplicate an object in Java?

The clone() method of the class java. lang. Object accepts an object as a parameter, creates and returns a copy of it.

Why there is no sizeof operator in Java?

Because the size of primitive types is explicitly mandated by the Java language. There is no variance between JVM implementations. Moreover, since allocation is done by the new operator depending on its argument there is no need to specify the amount of memory needed.


You can use the java.lang.instrumentation package.

It has a method that can be used to get the implementation specific approximation of object size, as well as overhead associated with the object.

The answer that Sergey linked has a great example, which I'll repost here, but you should have already looked at from his comment:

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


Look into https://github.com/DimitrisAndreou/memory-measurer.
Guava uses it internally, and ObjectGraphMeasurer is especially straightforward to use out-of-the-box, without any special command-line arguments.

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

The java.lang.instrument.Instrumentation class provides a nice way to get the size of a Java Object, but it requires you to define a premain and run your program with a java agent. This is very boring when you do not need any agent and then you have to provide a dummy Jar agent to your application.

So I got an alternative solution using the Unsafe class from the sun.misc. So, considering the objects heap alignment according to the processor architecture and calculating the maximum field offset, you can measure the size of a Java Object. In the example below I use an auxiliary class UtilUnsafe to get a reference to the sun.misc.Unsafe object.

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