• Post Reply Bookmark Topic Watch Topic
  • New Topic

String Buffer and memory usage question  RSS feed

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I had a question about the String buffer and memory allocation. I know "append" on StringBuffer and StringBuilder will not create string objects but am not sure about how the following line will execute
buffer.append("&#" + (int)chars[i] + ";");


This code is part of a static utility method which is called by another method.


Based on the exception thrown, I am assuming that in the background string objects are being created.
Exception stack referred to Line 5 in the following stack (but not shown here)
Exception created : java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390)
at java.lang.StringBuffer.append(StringBuffer.java:224)
 
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That line does create a String on the heap, before append() is called. Basically, you're creating

which is a String, before calling

However this string immediately becomes available for garbage collection, as nothing retains a reference to it. So I doubt this is causing an OutOfMemoryError. It might make things a little bit slower than they could be, but not much. Your real problem is elsewhere.

Specifically, although the StringBuilder is not (yet) creating a permanent String with all the new data, it is storing that data in a char[] array. And when you outgrow that char[] array, it needs to make a new, bigger one, and copy the data to that. If there's a lot of data there, that's what's causing your OutOfMemoryError.

There are various things you might try to do here, but the main one is: do you really need to have all this data in a single String or StringBuilder at once? What are you going to do with it then? Perhaps it's being written to a file, database, or the console? If so, perhaps you can write each bit of new data directly to that file/database/console/whatever, and not save it all up in memory first. That's generally the best strategy, if it's possible.
 
seena mathew
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:That line does create a String on the heap, before append() is called. Basically, you're creating

which is a String, before calling

However this string immediately becomes available for garbage collection, as nothing retains a reference to it. So I doubt this is causing an OutOfMemoryError. It might make things a little bit slower than they could be, but not much. Your real problem is elsewhere.

Specifically, although the StringBuilder is not (yet) creating a permanent String with all the new data, it is storing that data in a char[] array. And when you outgrow that char[] array, it needs to make a new, bigger one, and copy the data to that. If there's a lot of data there, that's what's causing your OutOfMemoryError.

There are various things you might try to do here, but the main one is: do you really need to have all this data in a single String or StringBuilder at once? What are you going to do with it then? Perhaps it's being written to a file, database, or the console? If so, perhaps you can write each bit of new data directly to that file/database/console/whatever, and not save it all up in memory first. That's generally the best strategy, if it's possible.



But do you think inside the loop, a new StringBuilder instance will be created on each iteration and that might be a cause?
Ideally any unreferenced object is supposed to be garbage collected. But the exception stack referred above mentioned method and a line number which was pointing to buffer.append(...) .

The method is actually called in a loop multiple times (15-20 times) by each logged in user.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, there is probably going to be another StringBuilder created and then made available for GC, once per loop iteration. But this still shouldn't have anything to do with an OOME, since it's easily available for GC. I suppose if you really want to mimimize the creation of unnecessary intermediate objects, you can replace the buffer.append() line with something like this:

That will be slightly more efficient. But I really believe it will have virtually no effect on whether you get an OutOfMemoryError. Also you might try pre-sizing the StringBuilder, creating it with a larger size to begin with, so it doesn't have to resize as many times. But again, that probably won't affect the OOME very much. Lastly, you can simply increase the heap size using the java -Xmx command option. That will have the biggest effect of avoiding OOME. But even that is not as good as what I suggested first, which is avoiding putting everything in one big String in the first place. IF you can, that is.
 
Ranch Hand
Posts: 5575
Eclipse IDE Java Windows XP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:

That will be slightly more efficient. But I really believe it will have virtually no effect on whether you get an OutOfMemoryError.

it makes difference.

if you do like this


compiler interprets as in

hence every loop unnecessary new string object will be created.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, clearly, as noted. That's why I suggested it, obviously. But those extra objects are not going to affect OutOfMemoryError, and they're really not a big deal. I am trying to encourage the original poster to concentrate on more important things.
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!