aspose file tools*
The moose likes Performance and the fly likes Size of Java Objects Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Performance
Bookmark "Size of Java Objects" Watch "Size of Java Objects" New topic
Author

Size of Java Objects

Anil C
Greenhorn

Joined: Jan 08, 2001
Posts: 16
How can we find the size of a Java object ? say if I wanna find amongst a Vector, a Hashtable and a DOM object containing the same data, which object takes the max space and how much, how to go about this ?
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Anil,
Interesting problem. I'm don't know of any straight forward way to figure out the size of an object.
If I had to do it, I would create an interface make all class I need this functionality return it's size.
Eg.

Any class will have to implement this interface and return the correct size. This is easy, because I could just add up the member instance variable and return this as a hardcoded value. For example,


A more generic way and the way you would have to go if you don't have access to the classes is to use reflection. Using reflection, you can get all the fields from an object and using a lookup table (for a datatype size) sum up the different types. This last approach is the most generic and also the most expensive in performance. The coding won't be trivial either.
-Peter

[This message has been edited by Peter Tran (edited January 08, 2001).]
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
FYI "Java Platform Performance" notes the following sizes (in bytes):
1 byte
2 char
2 short
4 int
4 float
8 long
8 double
4 reference (8 on a 64-bit system)
Although different JVMs may use different (probably larger) sizes.

Also, a profiler may help. You need to check if the profiler can give object specific size directly, or be clever as to how to find it indirectly.
--Mark
hershey@vaultus.com
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Hey Mark,
Your statement, "Although different JVMs may use different (probably larger) sizes" is incorrect. All primitives types are the same size across different JVMs. That's one way JAVA guarantees that code you write on one platform will run on a different platform.
In JAVA, an int type is always 4 bytes regardless of what JVM I use.
-Peter
Akin Kaldiroglu
Greenhorn

Joined: Oct 10, 2000
Posts: 9
Originally posted by Mark Herschberg:
FYI "Java Platform Performance" notes the following sizes (in bytes):
1 byte
2 char
2 short
4 int
4 float
8 long
8 double
4 reference (8 on a 64-bit system)
Although different JVMs may use different (probably larger) sizes.

--Mark
hershey@vaultus.com

Hello,
I agree with Peter that the sizes of all primitive types in Java are standard. For composite objects, it is not that clear.
And I don't know of any API call to get the size of an object. There might be two methods to estimate the size of an object:
1- Adding up the sizes of all the fields in the object. We know the sizes of primitives. For references, Steve Wilson and Jeff Kesselman notes in their book "Java Platform Performance" it is 4 bytes.
2- Other method would be measuring heap memory before and after you create your object.
Of course these wouldn't give you the exact amount but you can have more accurate guess after them.
Pages 57-61 of the book I mentioned above gives you some info and
a simple implementation to measure the size of an object.
Akin Kaldiroglu
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
I wasn't being very clear. Certainly objects reference sizes are not specified, and that's what may be different, and if so, larger.
But I believe, technically, primative storage sizes are also not specified. What the JVM does state is the range of the primative, e.g. a short ranges from -32k to 32k. However, if the JVM wishes to store this is 40 bytes, although inefficient, it is allowed. Alternatively, if some JVM may have some very clever data sharing or compression algorithm, which may reduce storage size. (I don't know of any offhand.)
Practically speaking, I would suspect that most JVMs use exactly the minimum number of bytes required for storing the values; but since I wasn't certain, I err'ed on the side of caution.
--Mark
hershey@vaultus.com
Anil C
Greenhorn

Joined: Jan 08, 2001
Posts: 16
Thank U all for the responses and the interest shown. (Oh! not that the issue is solved, but we are bringing in more clarity)
All primitive data types are of fixed size in Java(for ensuring portability) and it is my understanding that, that is Y we don't have a sizeof operator like in other languages. Please correct me if I am wrong.
Coming back to our topic...As Peter and Akin(first method) have suggested, if we find the primitive types of the attributes and add up the size, won't a Vector, Hashtable and DOM containing the same data have equal size? We know this is not the case in actual. I have already tried to find the size using the "RAM before and after instantiation" method (second method suggested by Akin)on the above three objects. It returned different sizes as expected but I cudn't explain the figures I got. Trying to find the memmory consumed by a primitive datatype using this method is also not yielding the expected results. Though the figures returned were consistant, that is Y I wanted to know whether there is any other way.
Akin, can U briefly explain the method given in "Java Platform Performance" if it is a more reliable one ?
Peter, where can I get more information about Profiler ?

Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Let me help clarify a few points:
- The Java Language Spec. specifies the "range of values" of primitives, not their storage size. On a 32 bit machine, an int will *most likely* take up 32 bits, but could take up more as Mark mentioned above. In addition, JVM implementations often compact byte, short, and char when used in arrays or fields of objects, but are not required to. Therefore, if a byte is stored in an object, it could take up 8 bits, or more. They are also normally promoted to an int when used as a local or on the stack.
- There is no sizeof in Java because, I believe, of its desire to be as platform neutral as possible. If the language specified that an int was 32 bits and a reference was 32 bits, this would cause problems on a 64 bit machine where native pointers are 64 bits.
- I know of no exact way to determine object size other than doing something like this:
Runtime rt = Runtime.getRuntime();
long mem1 = rt.freeMemory();
System.out.println("Free memory is: " + mem1);
//create an object
Object o = new Object();
long mem2 = rt.freeMemory();
System.out.println("Free memory is now: " + mem2);
System.out.println("Object size might be: " + mem2-mem1);
I don't have the Wilson/Kesselman book in front of me but I think this is similar to what they recommend. One problem with this approach, and I pointed this out when I reviewed their manuscript, is that if a GC occurs anywhere during this, you won't get the right result. And no, there is no way to turn off the GC.
Peter Haggar
------------------
author of: Practical Java


Senior Software Engineer, IBM
author of: Practical Java
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Mark,
[Original question deleted...I was told it wasn't a nice rhetorical question.]
Section 4.2 of the JLS states, "The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing Unicode characters."
The number of bits for that primitive type gives you the min/max range. For example, a short is 16 bits and the ranges are -(2^16) < x < (2^16)-1 = -32768 < x < 32767.
I'm not trying to rag on you, but it's important that you understand this fundamental JAVA concept. The size of the primitive types are the same across different JVMs and different platforms. That means a short will always be 16 bits (2 bytes). This will be true until the JLS changes.
-Peter
[This message has been edited by Peter Tran (edited January 09, 2001).]
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by Peter Tran:
The size of the primitive types are the same across different JVMs and different platforms. That means a short will always be 16 bits (2 bytes). This will be true until the JLS changes.

Peter, Sorry but your quote above is definitely untrue. Let's put this to one to bed...see my previous post. Bottom line: The range of values is guaranteed to be the same, ie. a byte will always be between -128 and 127 inclusive, a short from -32768 to 32767, etc. However, a JVM implementation is free to use 1K, or whatever it wants, to represent each type as long as it is limited to the spec'ed range of values.
Peter Haggar
------------------
author of: Practical Java
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Peter Hagger,
Okay. I see what you're saying. I give in. (I feel like I'm in a hostage situation...Of course I'm the one holding the hostage and told to give myself up.)
Thanks,
-Peter
Ps. Have you seen my challenge to you in the one of our earlier post?
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Peter, Yes I saw the challenge...I didn't take it...good thing though...I would have lost! See my post there.
Peter Haggar
------------------
author of: Practical Java
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
Quite an exciting thread we have.
Anil KC wrote:

if we find the primitive types of the attributes and add up the size, won't a Vector, Hashtable and DOMcontaining the same data have equal size? We know this is not the case in actual.

Well, yes and no. Fundamentally, the 3, 4...x object/primatives stored in any of those use the same size. However the Vector, Hashtable, and DOM may store them in different ways. For example, maybe the hashtable actually contains two references to each object, whereas a vector contains one (I'm making this up as an example). In that case, assuming all objects are the same size, the sizes are:
Vector = R*X + S*X
Hashtable = 2*R*X + S*X
where
R = the size of an object reference
S = the size of an object
X = the number of objects
So we see that although the "data size" is the same in both cases, the overall size is not.

This is actually similar with the side discussion Peter T, Peter H, and I have been discussing. There, the point Peter H and I made was that although the object range is specified, the container in which it is stored, is not (e.g. although short fits in 4 bytes, you can put it in a bigger box, say of 40 bytes). It's the same thing here. The Vector, Hashtable andDOM are boxes, which may be a different sizes. Just like a half empty bx takes up space in your room, these "boxes" will take up space on the heap.
--Mark
hershey@vaultus.com
[This message has been edited by Mark Herschberg (edited January 09, 2001).]
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Hehehe...This is one of those times in life when you remember a saying from your mother, "Stop while you're ahead." Or in my case, while you're behind...Wayyyy behind.
Thanks to Mark and Peter H. for showing me the way to Java-Nirvana.
-Peter
Binwei Yang
Greenhorn

Joined: Jan 09, 2001
Posts: 2
Another way to estimate how much memory a java.util.Vector takes relative to java.util.Hashtable is via serialization.
For example,
Vector v = new Vector ();
// add serializable objects to v
v.addElement (...);
...
Object[] elements = new Object[v.size()];
v.copyInto (elements);
Then write the Vector v and the array elements into two separate
files. The difference in size of the files should tell you the overhead of the Vector.
The motivation for this approach is that it accounts for not only the memory used by the class itself, but also its parent class(es).
Comments?
Binwei
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Binwei,
That's actually a pretty cool idea. Great suggestion.
-Peter
Anil C
Greenhorn

Joined: Jan 08, 2001
Posts: 16
Wow ! nice to see so much of Information. I have not been a regular vistor of Java Ranch, but I am 'thrilled' by this experience and wud now surely drop in more frequently.
Though I asked a general question, I think I shud tell now how it all came up. We were trying to find the overhead while using a DOM object(XML) to pass data between different layers in an application in comparison to a Vector or Hashtable.(which we were originally using). We knew DOM takes more space but wanted to know how much more.
As I had noted earlier, we tried out the 'free memory' method (using freeMemory method of Runtime class. Peter .H has given the code snippet above). The figures we got did give us a comparative idea but as I noted earlier, we cudn't explain the figures. Then we tried the serialisation way. (As Binwei has suggested). This also gave us a '% increase in size'for different types.
Being relatively new to Java, I had a doubt whether I am resorting to round about ways when there is a more perfect way existing. That is Y I decided to post the question here. I am really happy for having done so as I am now getting an insight into various related aspects like the intricasies of storage of datatypes.(and also happy to see that our approach to the problem was very similar to the various solutions suggested by Java experts here...a self pat ! )
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
Anil KC,
Can you post your results to the list? I'd be interesting in seeing the differences. Thanks.
--Mark
hershey@vaultus.com
Don Kostello
Greenhorn

Joined: Jan 17, 2001
Posts: 1
While the serialization approach may be useful, it also may not be. The reason is that some machines may want objects/primitives aligned on word boundaries. Thus, while a byte may only be 8 bits, some machines may want all of them aligned on 32 or 64 bit boundaries, and the actual storage used by them will be greater. This is generally the case with arrays, and is of course highly machine dependent. So, while the serialization may give a ROM estimate for the size of a given object, there is no absolute way to say how much memory that object will actually use. In addition, there is certainly some additional information in the classes which does not get serialized but is constructed and updated along with the instance, and this will not be reflected in the serialization size. But, as I said, it may give you a decent ROM estimate.
Kevin Mukhar
Ranch Hand

Joined: Nov 28, 2000
Posts: 83
Re: Determining size through serialization
If you are talking about true serialization, i.e.:
ObjectOutputStream out = ...
out.writeObject(myObject);
This will NOT give an accurate answer for the size of an object. In addition to the values of the members of the object, serialization writes metadata to the stream which describes the object and its fields. A serialized object will use more bytes that that object in memory.
Anil Vupputuri
Ranch Hand

Joined: Oct 31, 2000
Posts: 527
This thread is like a ever lasting love story..Finally
i got a pretty good link for this thread's answer.
Manage the Object
Anil

SCJP 1.5, SCEA, ICED (287,484,486)
Anil C
Greenhorn

Joined: Jan 08, 2001
Posts: 16
Originally posted by Mark Herschberg:
Anil KC,
Can you post your results to the list? I'd be interesting in seeing the differences. Thanks.
--Mark
hershey@vaultus.com

Mark.H,
Sorry, a bit tied up with work. I will surely post the results when I get some free time.
Peter.H,
What should I do to get into the race for a copy of ur book ? Or am I already in ?
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by Anil KC:
Peter.H,
What should I do to get into the race for a copy of ur book ? Or am I already in ?

Your in. Details are here.
Peter Haggar
------------------
Senior Software Engineer, IBM
author of: Practical Java
Sanket Meghani
Greenhorn

Joined: Jan 15, 2007
Posts: 14
Hello There,

This is indeed a very interesting discussion.

I still have some confusion about whether the size of primitive data type is uniform across JVMs or not? Because the discussion in this thread suggests that Java Specification only gives the range of values a variable of perticular data type can have. It does not say anything about the size of it.

But an article on Sun's site says that a byte is 8 bit signed number, short is 16 bit signed number .... and so on.

The link to the article is : http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html

Please throw some light to reduce the confusion.


Thank You.
Sanket Meghani.
Peter Chase
Ranch Hand

Joined: Oct 30, 2001
Posts: 1970
I guess you've searched and found this old thread. Searching is generally to be commended, but resurrecting years-old threads is not good practice in most bulletin boards including this one. Especially really long threads that take ages to scroll down!

A quick answer to your question, if I understand it correctly, is that Sun only specifies the data range of each type, not how much real memory it should take up. This is very deliberate, to allow maximum flexibility to JVM implementors. The representation of data types in real memory is too low-level a concept for Java programmers.

I'm going to close the thread, so if you have further questions, please raise a new topic.


Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Sean Collins
Greenhorn

Joined: Nov 16, 2009
Posts: 8
I'm going to close the thread

So maybe this reply won't work eh? Other bulletin boards that close threads on still-relevant topics provide some forward links - perhaps CR could consider something like that. This is on the first page of results for "get size of java object" from a well-known search engine, so perhaps the answer ought to be on it somewhere.

I haven't found the answer yet, but also considered the solution suggested by Binwei Yang. I discounted it before I saw this page on the basis that many objects have transient data. The application I'm working on has objects containing a large amount of transient data, so it'd be necessary to calculate the storage for the transients separately. I suspect many serializable API classes may use transients too, and even if you wrote some compensating code for those, you run the risk of API-preserving optimisations which add transients later. Rather than over-estimating, which the decorations used in a serialized stream might cause, transients would lead to under-estimating. The former would be inefficient in my application, the latter (the motivation for my search) is currently disastrous!

java.lang.instrument.Instrumentation appeared in 1.5, which has a getObjectSize(). I haven't tried it yet, but wondered whether it was a shallow object size or a deep object size? I thought Java Ranch would know! I'll have to do my own work, I guess. I'll try to remember to update when I know the answer if a guru doesn't beat me to it.

--updated: Shallow... may need to re-write my application in that case! A quick test of the facility, using code plagiarised from http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object tells me Strings are 20 bytes regardless of size, HashMaps are 40 bytes regardless of size.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Size of Java Objects