Memory usage of Java Strings and string-related objects (ctd)
In part one of this discussion, we looked at the memory usage of
a Java String. But a String isn't the only way to store character in memory data in Java.
Other objects can be used, with differing memory usage:
- the StringBuffer and (as of Java 5) StringBuilder classes store just
the buffer for the character data plus current length
(without the additional offset and hash code fields of a String),
but that buffer could be larger than the actual number of characters placed in it;
- if it suits our needs, we are free to implement any old CharSequence that we wish and potentially make it
take up less space than a String, StringBuffer or StringBuilder.
Memory usage of StringBuilder and StringBuffer
These classes are essentially implemented in the same way via a shared subclass and
their memory usage is identical. They differ in that
methods on StringBuffer are (fairly pointlessly, but for backwards compatibility) synchronized.
For simplicity, we'll refer to them generically as "string buffers" from now on, but our comments on memory usage apply
to both classes.
A string buffer requires the overhead of the object itself (from our discussion of
Java object memory usage recall that this is 8 bytes in Hotspot),
space for an int field (for the character count) and space for a reference to the underlying
char array. This comes to 16 bytes, and no "padding" is required.
The char arary in turn requires 12 bytes of overhead (as do arrays generally),
then two bytes per character capacity, rounding up to the next multiple of 8 as required.
So if the buffer is initialised to a 16 character capacity (the deafult for a newly-created "empty" buffer),
this gives 16+12+(16*2)=60, rounded up to 64 bytes.
It is important to note that when we call append(), the capacity of a
string buffer doubles until it can hold the next character to be added. Thus, creating
a default string buffer and then adding 17 characters will leave it with a capacity of 16*2=32 characters,
each character position needing two bytes.
and its memory usage will be 16+12+(32*2)=92, rounded up to 96 bytes.
Memory usage of a String created from a string buffer
As of Java 5, a String created from a string buffer takes up just enough space
to accommodate the characters in the string (and the usual String overhead), as per the
String memory usage formula given on the previous page. (In previous
versions of Java, the String could occupy more space as it "borroewd" the same
char buffer from the StringBuffer.)
Next: reducing memory used by Strings
Given the information presented so far, we consider how to reduce the amount of
memory occupied by Strings in a Java application.