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.
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.
See more on this question at Stackoverflow