Thursday, 11 November 2010

Java.String memory leak

Or "How I just saved myself 3 meg of precious Android heap memory".

I always glazed over whenever I came across how Strings are implemented in higher level languages. The most important advice I ever came across concerning them was "use a library that does all that string stuff for you". Of course I can make reasonable assumptions about how Java does strings:

1. There's a char buffer somewhere in there storing sequences of raw characters
2. It probably does something clever with them along the lines of the same way I do textures

So what happened? A loader parses an entire object file into a string, then passes a tokenized element of that string into an object as the object's name. It all seemed fine till I ran the Eclipse Memory Analysis Tool, when I found at the top of my memory usage hitlist a bit more than 3 megabytes of char data. As in, a couple of raw char[]. Full of, guess what? My entire object file.

"What's happened here?", I thought, stroking my chin. A closer look at my object in the debugger (a Submesh) revealed that sure enough, its name (supposed to be something like "grp 1"), which is a String, has the entire object file in its buffer. The String object stores an offset and length into the character buffer. The garbage collector looks at the 3 meg buffer and says "well, this Submesh object here still has a reference to this sequence of data, so I can't delete it!".

The fix is trivial: construct a new string from the passed in string, which makes a new buffer and frees up the old one for the GC's unreferenced memory hit squad.

I thought I'd post this because without running the MAT I never would have known I was leaking 3 megs of memory. It's worth checking.

1 comment:

  1. Welcome to Java strings. Bitting you in the behind since 1995!

    ReplyDelete