The data below is for Hotspot / Java 8 - numbers will vary for other JVMs/Java versions (for example, in Java 7, String has two additional int fields).
A new Object() takes 12 bytes of memory (due to internal things such as the object header).
A String has (number of bytes in brackets):
- an object header (12),
- a reference to a
char[] (4 - assuming compressed OOP in 64 bit JVM),
- an
int hash (4).
That's 20 bytes but objects get padded to multiples of 8 bytes => 24. So that's already 24 bytes on top of the actual content of the array.
The char[] has a header (12), a length (4) and each char (10 x 2 = 20) padded to the next multiple of 8 - or 40 in total.
The byte[] has a header (12), a length (4) and each byte (10 x 1 = 10) = 26, padded to the next multiple of 8 = 32.
So we get to your numbers.
Also note that the number of bytes depends on the encoding you use - if you retry with message.getBytes(StandardCharsets.UTF_16) for example, you will see that the byte array uses 40 bytes instead of 32.
You can use jol to visualise the memory usage and confirm the calculation above. The output for the char[] is:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 41 00 00 f8 (01000001 00000000 00000000 11111000) (-134217663)
12 4 (object header) 0a 00 00 00 (00001010 00000000 00000000 00000000) (10)
16 20 char [C.<elements> N/A
36 4 (loss due to the next object alignment)
Instance size: 40 bytes (reported by Instrumentation API)
So you can see the header of 12 (first 3 lines), the length (line 4), the chars (line 5) and the padding (line 6).
Similarly for the String (note that this excludes the size of the array itself):
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
12 4 char[] String.value [A, B, C, D, E, F, G, H, I, J]
16 4 int String.hash 0
20 4 (loss due to the next object alignment)
Instance size: 24 bytes (reported by Instrumentation API)
intfields only add up to 12 bytes, but there is an object header as well. The size of the array reference depends on the VM (32/64 bit) and its settings (whether it uses compressed pointers or not). Then there's the question of alignment and of course it would be nice to know howRamUsageEstimatoractually works. (And Java 8 did away with theoffsetandlengthfields.)