Name: ddT132432 Date: 10/08/2001
java version "1.4.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)
StringBuffer.toString() shares the character array with String,
so that one can efficiently build up a string in the buffer and take
the resulting String without copying.
If the StringBuffer is subsequently modified, it makes a copy of the character
array, and there is a common use of StringBuffer that leads to very inefficient
use of memory. Say one is parsing into a StringBuffer, emitting
String's, then zeroing the StringBuffer with setLength(0) for the next String.
These emitted strings are of length of the maximum length the StringBuffer
has reached to that point! If there has been a 200 character token, then
all future toString()'s make 200 character String's, even if they are just
a few characters long.
This problem has been stated as JavaOne and one can see this from the source
code, but it is very non-obvious, even surprising, and obviously
potentially hugely wasteful.
It should be easier to do the right thing. Perhaps it would be enough to
document this inefficient usage in the methods involved -- toString() and
setLength() -- with the suggestion to use StringBuffer.substring(0), which does
exactly what one might think toString() does. HotSpot has very efficient
memory allocation, so perhaps in some cases it would be efficient to create a
new StringBuffer for each new String at the same place as setLength(0),
but in some cases it's not clear what initial size should be, a size which
would have been established from previous parsing with the setLength(0)
approach, so making new StringBuffers either makes them too large or suffers
copying costs during expansion. (Having setLength(0) turn off the shared
flag works too late: the toString() String has already been created with
the overlong length.) Still, both options are implementation dependent,
and the knowledge not well advertised. Perhaps it would be better
to explictly define a function that does the right thing:
/**
Return the current contents of the buffer,
and clear the buffer for subsequent reuse.
Should be used instead of toString() / setLength(0).
*/
public String reset() {
String str = substring(0);
setLength(0);
return str;
}
(Review ID: 133281)
======================================================================
- duplicates
-
JDK-4822325 Remove String/StringBuffer sharing
-
- Resolved
-