Friday, December 12, 2008

The Size of a Boolean object in Java

Did you ever wonder how much memory is used by one single instance of a java.lang.Boolean?

One could guess 1 byte. After all, a Boolean only holds true or false, right?

That wasn't even close! I'll give you a hint: any Java Object has an 8 bytes header in 32 bits HotSpot VM. So you will think: "Ok, in this case, you have the 8 bytes header plus a byte for the value, so a Boolean takes up 9 bytes of memory!"

It got closer but you missed it by almost 50%. Any Java object is aligned to an 8 bytes granularity. A Boolean has 8 bytes of header, plus 1 byte of payload, for a total of 9 bytes of information. The JVM then rounds it up to the next multiple of 8.

So the correct answer is: One instance of java.lang.Boolean takes up 16 bytes of memory!

But wait, there is even more: if you have a class like this:
public class XYZ {
// other attributes go here
private boolean b;
// other attributes go here
};

And replace it with:
public class XYZ {
// other attributes go here
private Boolean b;
// other attributes go here
};

You are potentially trading 1 byte of memory storage for 20 bytes of memory storage (16 bytes of the Boolean instance plus 4 bytes of the reference).

So here are my suggestions:
  • Use primitive wrappers judiciously. You may want to simply stick with the primitive variables instead. If you want to have null semantics you can just add another boolean variable called isXSet and you have the same semantics with a lot less space.
  • Promote reuse of immutable classes when possible. At any point in time, you only need 2 instances of the Boolean class in your heap, one representing true and one representing false. It gets harder when using Integer or Float for instance, because there are too many possible values.
  • In this case the suggestion about null semantics above is even more valid.


Tomorrow I will publish a longer post about Java objects memory organization. Subscribe to my RSS feed to get the updates!

19 comments:

marcelo said...

i find the idea of using Boolean.TRUE and Boolean.FALSE very nice. it avoids having lots of Boolean wrappers in memory, and you get to keep the null semantics.

also, i agree that sometimes using the primitive instead of the wrapper can make a HUGE difference, depending on your application design...

nice article!

bbennett said...

Argh! If the class had up to 8 boolean fields declared it should use one byte only!
Fat java; very fat!

Cédrik said...

Measuring memory used is indeed a very difficult thing to do.

I have written an article about measuring the size of an HttpSession. Hint: it is much more complicated than what you think...

Shameless plug: measuring HttpSession sizes is a very small amount of the information provided by MessAdmin, my open-source monitoring utility. Check it out, you will like it! :-)


@bbennett
java.util.BitSet is the class you're looking for...

Mike Heath said...

That primitive field in your class will probably take up 4 bytes or 8 bytes depending on the JVM because class fields get aligned too. And it's not "fat Java", just about every language does this by default because it's faster to access memory this way.

If you're worried about wasting memory with multiple booleans (frankly in most applications it is asinine to worry about this) use a boolean array or an EnumSet.

So you can save a tiny bit of memory and be a tiny bit slower or you can use a tiny bit of memory and be a tiny bit faster.

Anonymous said...

Do you know how much memory datebase connection takes? dont use datebase, use local files.

Sam Beran said...

Eclipse generates a warning when you instantiate a Boolean for this very reason. Nobody should ever instantiate a Boolean. The constructor for Boolean should have been private.

Danny said...

More along Sam Beran's lines, wouldn't all booleans in any JVM take up a grand total of about 32kb then? Why would the JVM instantiate more than two booleans? Any instance of a boolean within your program can simply be a reference to one of these two objects.

I know this to be true for Integers if done the way Sam said. For example new Integer(1) creates a new Integer object. However Integer.valueOf(1) will re-use an integer already instantiated with this value from the object pool.

roopinder said...

Auto-boxing will help reduce the amount of boiler plate code. Just be careful of null referenced objects!

Anonymous said...

Should a boolean value not just consume 1 BIT of memory?

Other question: Does the BitArray get rid of the Java Overhead for each bit?

developmentech said...

1 byte vs. 16? in today's world where ordinary machines have their memory measure in gigabytes, you are going to quibble over 15 bytes? really?

Stanimir Simeonoff said...

on 64bit architecture it takes even more, what's the point?
Booleans are rarely instantiated and often that can be optimized by Hotspot. Short lived objects have not been an issue for quite a long time now.
And autoboxing never creates boolean objects anyways.

Integer takes as much memory as Boolean too.
Strings and char[] are usually one of the greatest memory eaters, concentrate there.

cheers

Domingos Neto said...

developmentech, the point is not about 15 bytes, I chose boolean because it is an extreme example, but it holds true to any other primitive wrapper.

Most people write high level code in Java, and for these people it doesn't really matter, because their code is buried below too many levels of abstractions and so many layers of frameworks that there is no point in trying to optimize away one reference.

Now, if you are writing high performance software, without layers of JSP and remote calls and proxies and templates, that's when you need to start thinking about writing high performance code.

Stanimir Simeonoff said...

Once more the statement that boolean (not object) takes one byte of memory has never been true under any known implementation (at least to me). It has always had a size of int (+the byte alignment). Otherwise boolean would have had horrid performance.

boolean[] however do take only a single byte, yet not just a single bit (to represent a single boolean, e.g. new boolean[7] takes 7 bytes+array object header+byte alignment (one extra byte most likely)).

In that aspect boolean and Boolean (when replaced w/ a constant like Boolean.TRUE or Boolean.FALSE or simple autoboxing) do take the same amount of memory [provided the constant memory allocation is taken forever being part of the bootstrap classes]. However, boolean[] and Boolean[] are not the same. Yet, if you need low-mem boolean[] (not very high performance, though) you shall resort on java.util.BitSet most of the time. (just bit ops for int/long is also an option)

cheers

Kieron Wilkinson said...

I once read that if you declare multiple (primitive) booleans next to each other in a class, they will be aligned and so only take up the memory required (i.e. declaring up to 32 booleans will take up 32 bits on a 32-bit CPU).

I'd say the JVM is pretty damn clever really.

Stanimir Simeonoff said...

Kieron, can you show the link where you read that.
Using more than a single boolean in a byte (or word) will require performing all the operations atomically (AND/OR for pure setting the value). e.g smth like:
LOCK OR ES:[EBX+xxx],2 to set the 2nd declared boolean to 'true'. Otherwise it risks to alter the values of all other packed booleans even if the thread otherwise never access them.
Using lock is not cheap on top of the necessary and/or/shl to transform into regular boolean.
Such approach (even though viable coding-wise) is bound to perform horrible.

Kieron Wilkinson said...

It was quite some time ago, I think in a Java certification book... But probably I am mis-remembering. Perhaps it was actually that four byte fields will take up the equivalent of just one int. I suppose this would make more sense given your explanation and that the JVM now does field re-ordering if it can...

Stanimir Simeonoff said...
This comment has been removed by the author.
Stanimir Simeonoff said...

Bytes can be addressed separately on most (all?) processor architectures so no atomic operations are necessary. Yet, non-aligned reads/writes are slower than aligned but it shall not be a big issue.

Btw, creating new Booleans has another downside (aside memory consumption). Boolean has final field (value) and if the object doesn't fall in good escape analysis it will issue a memory fence (effective equal to writing of a volatile).

Serguei Fedorov said...

I was looking for this info all over the place, thanks a lot! I thought that it would simply be 1 byte, True, false

http://www.blackravenplace.net