3

I have heard that a byte by itself takes up 4 bytes in memory, and a byte inside a byte array takes 1 byte, but what about a byte member variable inside an object that is within an array?

class SomeObject {
    byte iBite;
}

public static void main(String[] args) {
    SomeObject[] objs = ...
}

Will each SomeObject have its iBite variable only be 1 byte in memory?

Streak324
  • 153
  • 1
  • 3
  • 12
  • No, it will be 'a byte by itself' and take up 4 bytes, if for no other reason that object sizes will almost certainly be rounded up. – user207421 Nov 26 '15 at 06:15
  • 1
    Objects have at least an 8 byte overhead, and are aligned on 8-byte boundaries, your object is 8+1=9 bytes (at least), so will take up 16 bytes in memory. The array is storing references to objects, which are themselves at least 4 bytes long, so `SomeObject[100]` uses 100*(16+4)=2000 bytes (at least) of memory (assuming different objects assigned to full array), while `byte[100]` uses 100 bytes of memory. Both are in addition to the 12+ bytes of overhead for the array itself. – Andreas Nov 26 '15 at 06:57
  • A byte inside an object will take 1-4 bytes, depending on the phase of the moon. – Hot Licks Nov 26 '15 at 18:56
  • @Andreas An array of 100 "objects" takes 100 times the size of a single reference (ie, pointer). (The objects themselves of course take more, but they are allocated separately.) – Hot Licks Nov 26 '15 at 18:59
  • @HotLicks I know. That's why I said 100 * 4 for the references, plus 100 * 16 for the objects, i.e. **100** * (16 + **4**) = 2000 bytes. – Andreas Nov 26 '15 at 19:00
  • @Andreas - SomeObject[100] may not reference any objects at all. And even if it does, they are not part of the array object. – Hot Licks Nov 26 '15 at 19:02
  • @HotLicks Which is why I said "assuming **different** objects assigned to **full** array", i.e. references are not null and are not referencing the same objects. – Andreas Nov 26 '15 at 19:03
  • @Andreas - And who did you expect to understand that? – Hot Licks Nov 26 '15 at 19:05
  • At Dalvik Vm all fields need 32 bit except long and double which need 64bit (see http://stackoverflow.com/questions/10824677/is-dalvik-even-more-memory-hungry-than-hotspot-in-terms-of-object-sizes) – AlexWien Nov 26 '15 at 19:14

1 Answers1

5

A byte as a local variable is implemented as an int, so it takes 4 bytes.

A byte as a field of a class (like in your example) takes 1 byte of memory, but classes in memory are rounded up to multiples of 8 bytes on e.g. HotSpot JVMs. That said, if you have a class with multiple byte fields (or char or short fields), those will make more efficient use of memory.

Arrays are similar: each byte will take 1 byte, but the array as a whole will be rounded up to a multiple of 8 bytes on e.g. HotSpot JVMs.

You can experiment with this by hand using http://openjdk.java.net/projects/code-tools/jol/. If you use it, for example, on

public static class A {
    boolean f;
    byte g;
    int h;
}

I get

Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

org.openjdk.jol.samples.JOLSample_01_Basic.A object internals:
 OFFSET  SIZE    TYPE DESCRIPTION                    VALUE
      0    12         (object header)                N/A
     12     4     int A.h                            N/A
     16     1 boolean A.f                            N/A
     17     1    byte A.g                            N/A
     18     6         (loss due to the next object alignment)
Instance size: 24 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 6 bytes external = 6 bytes total

which exhibits pretty clearly that boolean and byte take one byte as object fields.

As you'd expect, char and short are 2 bytes, int and float are 4 bytes, long and double are 8 bytes.

https://stackoverflow.com/a/14782255/869736 explains some details on Dalvik, including that currently small fields like byte are in fact implemented with 4 bytes. Remember that these details are going to be VM-dependent.

Community
  • 1
  • 1
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • A byte as field of class needs 4 bytes. – AlexWien Nov 26 '15 at 18:33
  • @AlexWien not on normal HotSpot VMs. – Louis Wasserman Nov 26 '15 at 18:34
  • Event on hotspot, where have you your information from? – AlexWien Nov 26 '15 at 18:34
  • @AlexWien A single field will be padded out, so while a byte field may need 4 bytes, 4 byte fields will also only need 4 bytes. :) – biziclop Nov 26 '15 at 18:40
  • @AlexWien you can experiment with this by hand using http://openjdk.java.net/projects/code-tools/jol/, which is about as authoritative as it gets, since it comes from the OpenJDK folks who actually write Java. – Louis Wasserman Nov 26 '15 at 18:43
  • @LouisWasserman Even a naked `Unsafe.objectFieldOffset()` call will reveal the truth. – biziclop Nov 26 '15 at 18:48
  • At dalvik used in android I think it is 4 bytes. – AlexWien Nov 26 '15 at 18:50
  • You can improve your answer by adding, char, short, float and double ;-) – AlexWien Nov 26 '15 at 18:54
  • You answer is only valid for HotSpot, Dalvik is different you should note that, not only in th e.g at HostSpot... – AlexWien Nov 26 '15 at 19:02
  • @AlexWien The crucial requirement for implementing packed structures like this is for the hardware to support the update of a single byte in a word, without affecting its neighbours. This is needed for the Java Memory Model guarantees of multithreaded access, and if the CPU can't do it, the VM must store bytes unpacked. – biziclop Nov 26 '15 at 19:02
  • @biziclop So you mean its an caused by the ARM processors used in embedded devices, like ARM7 to 9 ? not by Dalvik itself? – AlexWien Nov 26 '15 at 19:04
  • Thank you for the jol tool. Never knew about it. – Streak324 Nov 26 '15 at 19:09
  • Even the statement about local variables is implementation dependent. While it is true that the bytecode instruction set doesn’t make a difference between `byte`, `short`, `char`, `boolean` and `int`, the implementation still is free to make a distinction when narrowing the type is possible (which can deduced from context). Similarly, the same instructions are use for dealing with arrays of type `byte` and `boolean`, but the JVM still might decide to store boolean arrays differently. Further, local variables might get mapped to CPU registers or optimized away entirely, taking no space at all. – Holger Nov 26 '15 at 19:28
  • @AlexWien I think so but I'm not that familiar with the ARM instruction set. – biziclop Nov 26 '15 at 19:30