5

If I need 8 boolean member variables in a class, does Java effectively place them all in one byte? Or will it use a byte for each? In other words, is the memory footprint different for:

boolean a;
boolean b;
boolean c;
boolean d;
boolean e;
boolean f;
boolean g;
boolean h;

vs.

public static final int a = 0x01;
public static final int b = 0x02;
public static final int c = 0x04;
public static final int d = 0x08;
public static final int e = 0x10;
public static final int f = 0x20;
public static final int g = 0x40;
public static final int h = 0x80;
byte flags;

I'm asking because I will be instantiating a lot of these objects. So having it take 1 byte instead of 8 bytes of memory will be a noticeable savings.

Update: This is definitely similar to the linked questions that list that a boolean is stored in an int (thank you for those links and sorry I didn't find them before asking). This question is a little different in that it presents the specific alternative of using a byte and bit flags. I don't know if this is sufficient to make this question not a duplicate.

Update 2: I just ran this using SizeofUtil and found the following. The 8 booleans requires 24 bytes/object or 3 bytes/boolean. The single byte approach requires 10 bytes/object. I would understand 8 where it's expanding a byte to a native int (I'm on a 64-bit system). But what's with the other 2 bytes?

David Thielen
  • 28,723
  • 34
  • 119
  • 193
  • My bet is that on 64 bit machine it will pack them 8 byes apart. But that's up to the JVM. Wasteful in terms of memory but not in terms of performance. – Bathsheba Dec 06 '13 at 17:09
  • yes it is more efficent – 0x90 Dec 06 '13 at 17:10
  • 2
    For self evident reasons the `boolean` must be the best data structure for holding booleans for usual requirements; otherwise something else would be used. I have a feeling that the usual requirements are probably access speed at the expense of memory. Do you want to sacrifice access speed? – Richard Tingle Dec 06 '13 at 17:13
  • Boolean is only the *best* type in terms of its *definition* by the JLS. In terms of speed, boolean has some quirks in the implementation of the VM, that make it potentially *slower* than uning a full int for the same purpose (using the C-style non-zero == TRUE). The problem with booleans is that they almost inevitably require byte code that introduces branching into the code (e.g. to implement "boolean b = x == y", where c-style could say "int b = x - y"). You can check this with javap. – Durandal Dec 06 '13 at 17:22

4 Answers4

7

The actual information represented by a boolean value in Java is one bit: 1 for true, 0 for false. However, the actual size of a boolean variable in memory is not precisely defined by the Java specification.

The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.

Hence it will be better to use byte if you are creating lots of booleans.

Azad
  • 5,047
  • 20
  • 38
Amit Sharma
  • 5,844
  • 5
  • 25
  • 34
4

Read the topic "How much memory does a boolean consume?". They suggest BitSet as solution for large sets of booleans, but in your case byte solves the problem better, because you won't have a large set of booleans, you will have a large set of 8 booleans objects.

Summarizing: byte is better than 8 booleans.

Italo Borssatto
  • 15,044
  • 7
  • 62
  • 88
  • Unless he comes up with a way to partition a BitSet so it is shared amongst the hundreds of objects with these 8 boolean fields... each object could have an index number `n`, and use fields `8*n` to `8*n +7` in the shared BitSet for the 8 booleans. That's probably messier than you really want to deal with. – dcsohl Dec 06 '13 at 17:23
  • @dcsohl It'll have almost the same result in memory usage, so I think using byte will be better. Like Andrey answer shows, in JDK they store booleans using masks too. – Italo Borssatto Dec 06 '13 at 17:25
  • Additional information: http://imagenious.wordpress.com/2008/02/05/java-bitset-vs-primitive/ – Italo Borssatto Dec 06 '13 at 17:37
  • 1
    @dcsohl A shared BitSet would require *some* form of reference to it, the reference woult eat at least as much memory as the byte does. Not a practical idea. – Durandal Dec 06 '13 at 17:38
  • Yah, you're right. Ok then. – dcsohl Dec 06 '13 at 17:57
  • FYI - I found a sizeof utility and it did show the byte approach is better (no surprise). But the number of bytes used each way was a bit weird. – David Thielen Dec 08 '13 at 18:46
  • @DavidThielen How did you measured it and what was the weird result? – Italo Borssatto Dec 08 '13 at 19:10
  • Please take a look at Update 2 above. Thanks – David Thielen Dec 09 '13 at 04:06
  • @DavidThielen They must be for the object and property references. In Java, an object reference takes 4 bytes on 32-bit systems and 8 bytes on 64-bit systems. I dont't know how much it takes to reference an property of theobject, but it seems to be 1 more byte. :) – Italo Borssatto Dec 09 '13 at 05:01
0

Its up to the VM how it will implement the fields in memory.

But common sense says that its much easier to implement with each field in its own memory slot in the object, and the size of it is also up to the VM, could be a byte or something larger (I'd guess int).

You can measure this for a particular VM by creating an array of a large number of these objects (lets say 10M) and check how much memory got used (Runtime API for example).

But I would only worry about this when I have a serious memory issue. Go with the booleans, you can re-implement it as a flag field when you really need to (provided you don't litter your code with direct field access and use getters).

Durandal
  • 19,919
  • 4
  • 36
  • 70
0

If one looks at the Spliterator of JDK 8, they are still using bit masks and the only reason for this I can think of is memory effeciency:

 public static final int DISTINCT   = 0x00000001;
 public static final int SORTED     = 0x00000004;
 public static final int ORDERED    = 0x00000010;
 public static final int SIZED      = 0x00000040;

So it should be a fine approach then.

Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68