I want to record how much memory (in bytes, hopefully) an object takes up for a project (I'm comparing sizes of data structures) and it seems like there is no method to do this in Java. Supposedly, C/C++ has sizeOf()
method, but this is nonexistant in Java. I tried recording the free memory in the JVM with Runtime.getRuntime().freeMemory()
before and after creating the object and then recording the difference, but it would only give 0 or 131304, and nothing in between, regardless of the number of elements in the structure. Help please!

- 6,498
- 11
- 46
- 94

- 2,611
- 4
- 24
- 30
-
6http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object – Sergey Grinev Feb 20 '12 at 21:38
-
1You may want to try the totalMemory() and then freeMemory() and subtract those instead. – Matt Feb 20 '12 at 21:40
-
5I recommend you taking a look at Jbellis JAMM. (https://github.com/jbellis/jamm) It relies on the instrumentation agent mentioned above but encapsulates some hepful utilities to deep measure the footprint of an entire object-graph. Looks simple and pretty cool to me. – Claudio Feb 26 '13 at 14:17
-
it will work only for primitive structures, not for structures with collections or something. Size of int[].class can be few bytes, but size of new int[1e9] will be few gigabytes. – Mikhail Ionkin Aug 21 '22 at 10:33
3 Answers
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()));
}
}

- 5,141
- 5
- 38
- 59

- 59,865
- 24
- 119
- 170
-
1Says "The only way to access an instance of the Instrumentation interface is for the JVM to be launched in a way that indicates the agent class - see the package specification. The Instrumentation instance is passed to the premain method of the agent class. Once an agent acquires the Instrumentation instance, the agent may call methods on the instance at any time. " <-- how do I do that (in Eclipse)? – Tyler Petrochko Feb 20 '12 at 21:47
-
Don't I have to specify how the JVM launches? I tried it and it keeps giving me NullPointerException – Tyler Petrochko Feb 20 '12 at 21:54
-
2
-
180Don't know how this answer has gotten so many upvotes. It completely ignores the fact that it is necessary to compile an agent class to pass to the JVM as an argument. Not doing so will render instrumentation null, and trigger a NullPointerException. Here's the proper answer: http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object – arkon Aug 16 '15 at 10:50
-
There must be something not quite right with this approach when trying to find my web session size: it reports 40, while ObjectGraphMeasurer (https://github.com/DimitrisAndreou/memory-measurer) reports "Footprint{Objects=34, References=52, Primitives=[float, int x 19, char x 257, long x 2, byte x 68557]}". ObjectGraphMeasurer is clearly the winner. – Yuci Sep 02 '16 at 11:03
-
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));
}
}

- 17,291
- 7
- 48
- 81

- 191,574
- 25
- 345
- 413
-
This was pretty helpful. Even the other one was very easy to make it work. Have you used this before? – Venki Apr 23 '12 at 18:24
-
2I've used memory-measurer before, yes. (I contribute to Guava, and I did mention that we use it internally. ;) ) – Louis Wasserman Apr 23 '12 at 18:27
-
Instant response. that's why i love SO. thanks a ton. I am trying to use it to measure up a memory activity. it has come in very handy. – Venki Apr 23 '12 at 18:35
-
8I suspect that the most frequent SO users come here to procrastinate -- so of course we're on here _all the time,_ and we respond to comments instantly. – Louis Wasserman Apr 23 '12 at 18:46
-
@LouisWasserman if I am getting an output of Footprint{Objects=40004, References=92773, Primitives=[int x 40004, float]}, what is the total size? – Ani Jun 16 '14 at 22:50
-
1That varies depending on your JVM. If you want to measure bytes, then you should be using `MemoryMeasurer` from the same project; follow the instructions there. – Louis Wasserman Jun 16 '14 at 23:31
-
@LouisWasserman If I use 64 bit JVM, can you tell me how to do the calculations? – Ani Jun 17 '14 at 15:31
-
You need to know if CompressedOops is on, but in that case you should assume an Object has a 12 byte overhead, and that references, ints, and floats each take 4 bytes. – Louis Wasserman Jun 17 '14 at 15:44
-
Very helpful. But this jar has a dependency of guava. It's not a executable jar :( – kamushin Dec 16 '15 at 08:21
-
-
@LouisWasserman emmmm..I added all jars in lib into my build path, but when I run my server, I got `java.lang.NoClassDefFoundError: com/google/common/base/Predicates`. So I have to add `guava` dependency in my `pom.xml`. It seems `guava-r09.jar` does't work. – kamushin Dec 16 '15 at 08:31
-
-
-
That sounds like a problem with your maven setup? But you can download the Guava jar from the github site. – Louis Wasserman Dec 16 '15 at 08:44
-
@LouisWasserman I download `memory-measurer` jar from github. I didn't know I can get `memory-measurer` from maven. – kamushin Dec 16 '15 at 08:49
-
-
1@rodi Linear in the result, but with a pretty high constant factor due to reflection. – Louis Wasserman Mar 08 '16 at 20:03
-
-
-
I mean, it's also O(# objects in the object graph), which is somewhat tighter I suppose? For e.g. an int array it'll be O(1). – Louis Wasserman Mar 08 '16 at 20:23
-
I went with JAMM per the answer below, you can get it from Ivy/SBT and it does not require Guava (which I often avoid from scala). Just my 2 cents. – Daniel Langdon May 26 '16 at 15:58
-
Wonder if I should use this version instead https://github.com/msteindorfer/memory-measurer as DimitrisAndreou's version is not maintained any more? – Yuci Sep 02 '16 at 11:06
-
is this available in maven central? I can't seem to get the library from maven. is there any private distribution for this package? – ahrooran Mar 11 '23 at 17:57
-
memory-measurer jar not working. I passed jar like this: -javaagent:D:\company\javaagents\object-explorer.jar – ahrooran Mar 11 '23 at 18:27
-
Error message says Instrumentation is not setup properly. You have to pass -javaagent:path/to/object-explorer.jar to the java interpreter – ahrooran Mar 11 '23 at 18:27
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() { }
}

- 8,855
- 7
- 47
- 94
-
1I'm not sure about this: ((int)maxOffset/WORD) + 1)*WORD, but I think it does work as I'm pretty sure 64 bit variables are never crosssing an 8 byte boundary in a 64-bit VM. Good code otherwise, although you could of course get rid of the whole map making effort. I made my own version which also handles object arrays here: http://tinybrain.de/1011517 (would still need to add primitive arrays). – Stefan Reich Oct 30 '17 at 22:27