How to efficiently manage memory using Strings?

Consider a sample piece of code.

public void testString()
{     
    int i = 0;
    while(i < 100000000)
    {
        String s ="Hi hello bye" +i;
        i++;          
    }
}

In each iteration, a new String is created and its value is no longer needed for the next iteration. I tried printing the memory consumed pre and post this testString() functionality. Here are their values.

Before invoking testString():

Total Memory: 91684864 (87.4375 MB)
Max Memory:   1360855040 (1297.8125 MB)
Free Memory:  72163552 (68.82052612304688 MB)

After invoking testString():
Total Memory: 424280064 (404.625 MB)
Max Memory:   1360855040 (1297.8125 MB)
Free Memory:  171766816 (163.80960083007812 MB).

I see a large amount of memory being used and am afraid JVM Heap may go out of bounds due to the current way of handling Strings. The String generated for iteration 1 is no longer needed in iteration 2 and its storage space can be freed. I believe that is not happening here.

I tried using StringBuffer and StringBuilder objects and there seems a very marginal improvement in the memory usage.

Kindly assist me a better and optimal approach.

Jon Skeet
people
quotationmark

The String generated for iteration 1 is no longer needed in iteration 2 and its storage space can be freed. I believe that is not happening here.

It definitely is happening.

You're creating 100 million strings, each of which is at least 13 characters - and most of which will be about 20 characters. Each string consists of an object (which has overhead) and a char[] - so I'd guess at it taking around 60 bytes for a 20-character string.

If garbage collection weren't being effective, 100 million objects requiring 60 bytes each would require 6GB - whereas you're seeing a total memory which is only about 300MB larger than it was to start with.

The strings are being collected - just not immediately.

You haven't told us what you need to do with the strings in your real code (I'm assuming there's a real motivation for this) - assuming you actually need a string in each iteration of a loop, I don't think using StringBuilder is going to help you. If you only need the data is a StringBuilder then you can make it a lot more efficient, but it's rare that you create a StringBuilder but don't call toString on it.

people

See more on this question at Stackoverflow