For example, let's say I have an application that can read in a CSV file with piles of data rows. I give the user a summary of the number of rows based on types of data, but I want to make sure that I don't read in too many rows of data and cause OutOfMemoryErrors. Each row translates into an object. Is there an easy way to find out the size of that object programmatically? Is there a reference that defines how large primitive types and object references are for a VM?

Right now, I have code that says read up to 32,000 rows, but I'd also like to have code that says read as many rows as possible until I've used 32MB of memory. Maybe that is a different question, but I'd still like to know.

@Stefan Nice hint! Can you please tell, what will be the size of byte[0], byte[1], byte[5], int[0], int[1], int[2] using the approach you described? It would be nice, if results include overhead for length of array and memory alignment.
–
dma_kMar 8 '10 at 11:28

4

I tried this and got strange and unhelpful results. Strings were always 32, regardless of size. I thought this was maybe the pointer size but for another immutable class I created, I got 24. It works well for primitives but then you don't really need a program to tell you how big a char is.
–
BrelSep 16 '11 at 12:39

31

@StephenC - What is the point of your comment? It's not "obvious" that a String object doesn't contain its character array. A string IS a character array. They are synonyms. And in Java a String object includes a character array, and a few housekeeping integers. The person asking the question and I were hoping to find out how much memory all that took up. The code provided failed to give a helpful answer. This is important information. Unless you can provide some insight as to how to determine the size, I ask you again : what is the point of your comment?
–
BrelDec 19 '11 at 16:08

5

@Brel this solution is only an "approximation of the amount of storage consumed by the specified object", as specified in the documentation. Also I suppose that the authors decided to set the size of a String as 32 bytes (only the pointer?) because of the Java's String pool, which makes it difficult to say, whether a String instance is shared (stored in the pool) or local&unique to a class.
–
Andrei IJul 17 '13 at 8:33

6

How I can user ObjectSizeFetcher, if don't export jar? I have test java project in eclipse.
–
YShinkarevAug 5 '13 at 18:40

Some years back Javaworld had an article on determining the size of composite and potentially nested Java objects, they basically walk through creating a sizeof() implementation in Java. The approach basically builds on other work where people experimentally identified the size of primitives and typical Java objects and then apply that knowledge to a method that recursively walks an object graph to tally the total size.

It is always going to be somewhat less accurate than a native C implementation simply because of the things going on behind the scenes of a class but it should be a good indicator.

Alternatively a SourceForge project appropriately called sizeof that offers a Java5 library with a sizeof() implementation.

P.S. Do not use the serialization approach, there is no correlation between the size of a serialized object and the amount of memory it consumes when live.

Firstly "the size of an object" isn't a well-defined concept in Java. You could mean the object itself, with just its members, the Object and all objects it refers to (the reference graph). You could mean the size in memory or the size on disk. And the JVM is allowed to optimise things like Strings.

So the only correct way is to ask the JVM, which a good profiler (I use YourKit), which probably isn't what you want.

However, from the description above it sounds like each row will be self-contained, and not have a big dependency tree, so the serialization method will probably be a good approximation on most JVMs. The easiest way to do this is as follows:

Remember that if you have objects with common references this will not give the correct result, and size of serialization will not always match size in memory, but it is a good approximation. The code will be a bit more efficient if you initialise the ByteArrayOutputStream size to a sensible value.

Serialization won't keep track of transient variables, and the default serialization method writes strings in UTF-8, so any ANSI characters will only take one byte. If you have many strings, your size will be so far off as to be useless.
–
TMNJul 9 '12 at 18:45

while this may not give the exact size, for my needs I only needed a comparison between 2 object and SizeOf won't initialize from a web app. Thanks!
–
Is7aqOct 30 '12 at 22:57

If you would just like to know how much memory is being used in your JVM, and how much is free, you could try something like this:

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();
// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();
// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

edit: I thought this might be helpful as the question author also stated he would like to have logic that handles "read as many rows as possible until I've used 32MB of memory."

This is not a good solution, as you never know when a garbage collect will happen, or how much extra memory will be allocated to the heap at once.
–
Nick FortescueSep 9 '08 at 17:24

4

That is true, and I wouldn't intend this to address the main question of this post, but it might help him to know programmatically when he is getting somewhat close to hitting the max heap size.
–
matt bSep 9 '08 at 17:25

1

Other problem of this solution is when you are in a multi-thread environment (like in a web server). It's possible that other threads was in execution and consuming memory. With this approximation your are calculating used memory in all the virtual machine.
–
angelcerveraFeb 24 '13 at 10:34

Another disadvantage is that freeMemory returns an approximation. Try creating a javax.crypto.Cipher object. The difference between two calls to freeMemory (to estimate the size of a Cipher) is not constant !
–
EugenMay 9 '13 at 15:08

Aren't the sizes of various primitives defined in the Java Specification? (§2.4.1)
–
ericksonSep 9 '08 at 17:25

4

Not in the sense of "how much memory does it occupy," which is the question. Only in the sense of how they operate. For example, bytes, chars, and shorts take up an entire word on the Java stack, even though they operate with rounding etc..
–
Jason CohenSep 9 '08 at 17: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.

Interesting approach, but doesn't this suppose the object and its fields storage is not fragmented ?
–
Julien NicoulaudJun 11 '12 at 13:25

Yes and I don't know any JVM implementation that makes such fragmentation.
–
Miguel GamboaJun 18 '12 at 16:44

I don't understand. Fragmentation is not an option :) Let's take the example of object C which is stored as a field of objects A and B. Doesn't it shift the whole thing in either A or B ?
–
Julien NicoulaudJun 19 '12 at 13:46

Sorry, but I am not understanding either your point of view. According to my interpretation, in Java objects cannot be stored inside other objects, like happens with C structures or Value Types in .Net. So when you say: “object C which is stored as a field of objects A and B” that means that objects A and B have fields that store references (pointers) to the object C. Then the size of A and B are equals to the offset of that field plus the size of a reference (pointer) to the object C. And the size of a reference is the size of one word.
–
Miguel GamboaJun 19 '12 at 14:24

You have to measure it with a tool, or estimate it by hand, and it depends on the JVM you are using.

There is some fixed overhead per object. It's JVM-specific, but I usually estimate 40 bytes. Then you have to look at the members of the class. Object references are 4 (8) bytes in a 32-bit (64-bit) JVM. Primitive types are:

boolean and byte: 1 byte

char and short: 2 bytes

int and float: 4 bytes

long and double: 8 bytes

Arrays follow the same rules; that is, it's an object reference so that takes 4 (or 8) bytes in your object, and then its length multiplied by the size of its element.

Trying to do it programmatically with calls to Runtime.freeMemory() just doesn't give you much accuracy, because of asynchronous calls to the garbage collector, etc. Profiling the heap with -Xrunhprof or other tools will give you the most accurate results.

@dma_k, Java doesn't have real booleans actually. The size of boolean is 4bytes outside arrays and 1byte within boolean[]. Actually all primitives non double/long types are 4 bytes. The latter are 8 (the answer wrongly puts them as 4 too)
–
bestsssDec 25 '12 at 14:43

@bestsss Sorry, that was a typo. Thanks for pointing it out.
–
ericksonDec 26 '12 at 4:04

@bestsss: To be more exact, minimal memory allocation depends on the platform and implementation of JVM. Also objects on heap are aligned, so after summing up all sizes one need to round up.
–
dma_kDec 29 '12 at 9:52

There isn't a method call, if that's what you're asking for. With a little research, I suppose you could write your own. A particular instance has a fixed sized derived from the number of references and primitive values plus instance bookkeeping data. You would simply walk the object graph. The less varied the row types, the easier.

If that's too slow or just more trouble than it's worth, there's always good old-fashioned row counting rule-of-thumbs.

General concept is allocate objects and measure change in free heap space. The key being getFreeMemory(), which requests GC runs and waits for the reported free heap size to stabilize. The output of the above is:

nested: 160000 each=16
static nested: 160000 each=16

Which is what we expect, given alignment behavior and possible heap block header overhead.

The instrumentation method detailed in the accepted answer here the most accurate. The method I described is accurate but only under controlled conditions where no other threads are creating/discarding objects.

Did you tested this class with values ? I tried, but for me, incorrect values !!!.
–
DéboraAug 17 '14 at 14:26

The values it gave me for a simple object were about correct, but off by a factor of 10 for a list containing 1mio objects. Still, very nice work!
–
Michael BöcklingAug 21 '14 at 13:12

Interesting. I have tested it using JDK7u67, on Windows 7 x64 and Linux 2.6.16/x86_64, using each of 32bit/64bit/oop address modes. I have compared it to memory dumps analysed in Eclipse Memory Analyzer 1.3.x. What setup are you using? Do you have a specific example I could try?
–
dlaudamsSep 9 '14 at 5:43

Back when I worked at Twitter, I wrote a utility for calculating deep object size. It takes into account different memory models (32-bit, compressed oops, 64-bit), padding, subclass padding, works correctly on circular data structures and arrays. You can just compile this one .java file; it has no external dependencies:

This way you read the used memory before and after, and calling the GC just before getting the used memory you lower the "noise" almost to 0.

For a more reliable result you can run your job n times, and then divide the used memory by n, obtaining how much memory one run takes. Even more, you can run the whole thing more times and make an average.

JOL (Java Object Layout) is the tiny toolbox to analyze object layout schemes in JVMs. These tools are using Unsafe, JVMTI, and Serviceability Agent (SA) heavily to decoder the actual object layout, footprint, and references. This makes JOL much more accurate than other tools relying on heap dumps, specification assumptions, etc.

To get the sizes of primitives, references and array elements, use VMSupport.vmDetails(). On Oracle JDK 1.8.0_40 running on 64-bit Windows (used for all following examples), this method returns

You can get the shallow size of an object instance using ClassLayout.parseClass(Foo.class).toPrintable() (optionally passing an instance to toPrintable). This is only the space consumed by a single instance of that class; it does not include any other objects referenced by that class. It does include VM overhead for the object header, field alignment and padding. For java.util.regex.Pattern:

You can get a summary view of the deep size of an object instance using GraphLayout.parseInstance(obj).toFootprint(). Of course, some objects in the footprint might be shared (also referenced from other objects), so it is an overapproximation of the space that could be reclaimed when that object is garbage collected. For the result of Pattern.compile("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$") (taken from this answer), jol reports a total footprint of 1840 bytes, of which only 72 are the Pattern instance itself.

If you instead use GraphLayout.parseInstance(obj).toPrintable(), jol will tell you the address, size, type, value and path of field dereferences to each referenced object, though that's usually too much detail to be useful. For the ongoing pattern example, you might get the following. (Addresses will likely change between runs.)

My answer is based on the code supplied by Nick. That code measures total amount of bytes which are occupied by the serialized object. So this actually measures serialization stuff + plain object memory footprint (just serialize for example int and you will see that total amount of serialized bytes is not 4). So if you want to get raw byte number used exactly for your object - you need to modify that code a bit. Like so:

This answer is not related to Object size, but when you are using array to accommodate the objects; how much memory size it will allocate for the object.

So arrays, list, or map all those collection won't be going to store objects really (only at the time of primitives, real object memory size is needed), it will store only references for those objects.

How can a 4-byte integer and an object reference of unknown size fit into 4 bytes?
–
EJPMay 4 at 1:14

@EJP I mean to say all the object REFERENCE needs only 4 bytes of memory. It may be String reference OR Double object reference, But depends on object creation the memory needed will vary.
–
Kanagavelu SugumarMay 4 at 4:50

I doubt you want to do it programmatically unless you just want to do it once and store it for future use. It's a costly thing to do. There's no sizeof() operator in Java, and even if there was, it would only count the cost of the references to other objects and the size of the primitives.

One way you could do it is to serialize the thing to a File and look at the size of the file, like this:

Of course, this assumes that each object is distinct and doesn't contain non-transient references to anything else.

Another strategy would be to take each object and examine its members by reflection and add up the sizes (boolean & byte = 1 byte, short & char = 2 bytes, etc.), working your way down the membership hierarchy. But that's tedious and expensive and ends up doing the same thing the serialization strategy would do.