I'll try explaining the numbers referenced in the source article.
The article describes object metadata typically consisting of: class, flags and lock.
The class and lock are stored in the object header and take 8 bytes on 32bit VM. I haven't found though any information about JVM implementations which has flags info in the object header. It might be so that this is stored somewhere externally (e.g. by garbage collector to count references to the object etc.).
So let's assume that the article talks about some x32 AbstractJVM which uses 12 bytes of memory to store meta information about the object.
Then for char[]
we have:
- 12 bytes of meta information (8 bytes on x32 JDK 6, 16 bytes on x64 JDK)
- 4 bytes for array size
- 2 bytes for each character stored
- 2 bytes of alignment if characters number is odd (on x64 JDK:
2 * (4 - (length + 2) % 4)
)
For java.lang.String
we have:
- 12 bytes of meta information (8 bytes on x32 JDK6, 16 bytes on x64 JDK6)
- 16 bytes for String fields (it is so for JDK6, 8 bytes for JDK7)
- memory needed to store char[] as described above
So, let's count how much memory is needed to store "MyString"
as String
object:
12 + 16 + (12 + 4 + 2 * "MyString".length + 2 * ("MyString".length % 2)) = 60 bytes.
From other side we know that to store only the data (without information about the data type, length or anything else) we need:
2 * "MyString".length = 16 bytes
Overhead is 60 / 16 = 3.75
Similarly for single character array we get the 'maximum overhead':
12 + 16 + (12 + 4 + 2 * "a".length + 2 * ("a".length % 2)) = 48 bytes
2 * "a".length = 2 bytes
48 / 2 = 24
Following the article authors' logic ultimately the maximum overhead of value infinity is achieved when we store an empty string :).