[MUD-Dev] [TECH] String Classes, Memory Management, and Fragmentation

Kwon Ekstrom justice at softhome.net
Wed Jul 18 01:45:40 New Zealand Standard Time 2001


Disclaimer: Once again, mostly java implementation details.

From: <Daniel.Harman at barclayscapital.com>

>   // Assume buffer is a previously instantiated string buffer of
>   // size 5000

>   String s1 = buffer.toString();

I looked at the java source and what actually happens here is the
StringBuffer returns:

  new String(this)

It all pretty much adds up to the same thing, the new String and the
StringBuffer currently share a char[], which isn't a good thing if
you're buffer isn't full.

>   buffer.setLength( 0 ); // We now have two buffers of size
>   5000. One referenced by s1 and one referenced by buffer.
>   Remember StringBuffers don't ever shrink.

I just checked, this is incorrect... the source from
java.lang.StringBuffer shows:

        } else {
            // If newLength is zero, assume the StringBuffer is being
            // stripped for reuse; Make new buffer of default size
            value = new char[16];
            shared = false;
        }

Where newLength is the length that is input.  In this case it
recreates the char array with a length of 16.  How old is the book?
I'm using jdk1.3, so the assumption may be correct for an older
version.

What this means for the rest of this example should be
self-evident...

>   // uh oh we now have 3 x 5000 char arrays.

Actually we have 1 x 5000 array, and 2 x 16char arrays under the
java 2 1.3 implementation.

> Anyway the book goes on to say the moral of the story is to not
> reuse string buffers because both they and strings reference
> hidden character buffers.

> The book I'm referencing is 'Java 2 performance and idiom guide'
> by Craig Larman and Rhett Guthrie.

> Oh, as an aside, Kwon mentions using s1 = buffer.subString(0, len
> ) as a way of forcing the creation of a new correctly sized
> character array for s1. At least thats how I understood it.

Correct, when I posted previously, I hadn't looked at the
StringBuffer much, a prefered usage would be:

  buffer.subString(0);

This actually calls:

  this.subString(start, count)

Where start is the input value, and count is the number of "used"
characters.

The length method returns the integer which stores the number of
characters that are being "used" currently.

In most situations tho, you can simply use:

  String out = "output";
  out += "added data";

Please note that java interprets anything between quotes as a new
String automatically.  thus "bleh" is equal to new String("bleh"),
except that in the latter you actually create 2 Strings.

Oh yes, almost forgot, the StringBuffer grows it's buffer
dynamically, similar to a Vector.  It increases capacity by
(length+1)*2.

This leads to some interesting assumptions... for example the
following code:

  StringBuffer buf = new StringBuffer();
  buf.ensureCapacity(30);

The default capacity is 16, so (16+1)*2 would be 34.  After
increasing the capacity, instead of the 30 char buffer you wanted,
it would give you a 34 char buffer.

  buf.ensureCapacity(75);

Since we now have 34 chars, it'd be (34+1)*2 which is 70.  75 being
greater it would instead choose your input value and the buffer
would be exactly 75 chars in length... A minor detail, but if you
don't want those empty chars to be copied, use subString...  Because
there will always be additional characters, even if you don't reuse
the buffer... which apparently (at least for jdk1.3) does shrink
it's capacity.

-- Kwon Ekstrom

Disclaimer: java.lang.StringBuffer is owned and copywrited by Sun
Microsystems, any source used is simple for demonstration.

_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev



More information about the MUD-Dev mailing list