Re: Problem with StringBuffer
Wolfgang Muees wrote: > > Am Mit, 29 Mär 2000 schrieb Tatu Saloranta: > > I finally found out the reason for 'memory leak' on my Java program, > > and the culprit in this case was StringBuffer - implementation. > > ... > > (or length of the buffer via setLength()). The problem here is that > > as soon as I encounter a long token (~4000 chars in this case), > > _all_ tokens after that will use up the same 4k memory > > The right solution for this problem is IMO: don't reuse StringBuffer. > It is designed primary as an input buffer for a single string. I think I disagree here; at least if there's no other class for similar purpose. I am interested in optimizing Java-programs, and in general, one of the most efficient optimizations is to recycle objects. Object creation is not a cheap operation. Especially in this case, where StringBuffer does allocate a character array, it means there are at least 2 memory allocations and other initialization code. If the array truncation can be done when the array is being copied (during destringify() or whatever the method was), it won't add a new array allocation. An alternative would then be a replacement for StringBuffer that would be designed to be reusable. Not a huge task, and perhaps it might be worth the effort, at least in my case. In any case, I guess it all depends on how difficult it is to alleviate the problem. The fundamental problem I guess is that although it is String() instance that should really do the truncation (so as not to use huge char array for storing just few characters), it is StringBuffer that is responsible for doing that; String just takes the given array and length, and after that passively just uses what it got. JDK-fix notes that, and alleviates the problem so that none of the resulting strings have higher than 100% overhead. :-) In any case I think it's an oversight in developers of Java base classes; if they had known the problem, there would be something in description of StringBuffer - class to indicate it's not supposed to be reused. -+ Tatu +-
Re: StringBuffer patch.
Mo DeJong writes: > Between revisions 1.11 and 1.12 of > libraries/javalib/java/lang/StringBuffer.java > the access of the StringBuffer.ensureCapacity(int)V method was changed > from public to private. Oops, my fault -- should be fixed now. -Archie ___ Archie Cobbs * Whistle Communications, Inc. * http://www.whistle.com
Re: Problem with StringBuffer
Wolfgang Muees writes: > > I finally found out the reason for 'memory leak' on my Java program, > > and the culprit in this case was StringBuffer - implementation. > > > > I have a lexer (made with JFLex), that uses StringBuffer for > > constructing > > the strings for certain tokens. The StringBuffer is reused so that each > > time a new such token is getting creted, StringBuffer.setLength(0) is > > called. However, in Kaffe's implementation at least, the actual length > > of the buffer is not changed. This wouldn't be a big problem in itself, > > as there's just one StringBuffer instance... But, alas, as Strings & > > StringBuffers are optimized so that when new String(StringBuffer) is > > called, the character array is actually shared between the string > > and string buffer, until the StringBuffer needs to change the data > > (or length of the buffer via setLength()). The problem here is that > > as soon as I encounter a long token (~4000 chars in this case), > > _all_ tokens after that will use up the same 4k memory > > The right solution for this problem is IMO: don't reuse StringBuffer. > It is designed primary as an input buffer for a single string. Yesterday I checked in some changes which should alleviate this problem nonetheless.. please give them a try and let us know if they help. -Archie ___ Archie Cobbs * Whistle Communications, Inc. * http://www.whistle.com
StringBuffer patch.
Hello. Between revisions 1.11 and 1.12 of libraries/javalib/java/lang/StringBuffer.java the access of the StringBuffer.ensureCapacity(int)V method was changed from public to private. +private void ensureCapacity(int minCapacity) { + if (minCapacity <= 0) + return; + synchronized (this) { + ensureCapacity(minCapacity, false); + } } -public synchronized void ensureCapacity ( int minimumCapacity ) { - intn; - char[] oldBuffer; +// This method assumes synchronization This was an error, the method should be public. The change generated errors like the following in my code. l:/home/mo/project/kaffe/install/share/kaffe/Klasses.jar \ /home/mo/bin/jikes -g \ -d /home/mo/project/tcljava/unix/Kaffe/jacl \ tcl/lang/*.java sunlabs/brazil/util/regexp/*.java Found 6 semantic errors compiling "tcl/lang/FileUtil.java": 89. absBuf.ensureCapacity(absBuf.length() + path.length()); <> *** Error: Method "void ensureCapacity(int $1);" in class "java/lang/StringBuffer" has private access. Therefore, it is not accessible in class "tcl/lang/FileUtil". The following patch fixes the problem. Sat Apr 1 08:00:00 PST 2000 Mo DeJong <[EMAIL PROTECTED]> * libraries/javalib/java/lang/StringBuffer.java: fixed problem with ensureCapacity() method, it was accidently changed to private access when it should have been public. Index: libraries/javalib/java/lang/StringBuffer.java === RCS file: /cvs/kaffe/kaffe/libraries/javalib/java/lang/StringBuffer.java,v retrieving revision 1.12 diff -u -r1.12 StringBuffer.java --- libraries/javalib/java/lang/StringBuffer.java 2000/03/31 23:29:591.12 +++ libraries/javalib/java/lang/StringBuffer.java 2000/04/01 12:43:13 @@ -104,7 +104,7 @@ } } -private void ensureCapacity(int minCapacity) { +public void ensureCapacity(int minCapacity) { if (minCapacity <= 0) return; synchronized (this) { Mo Dejong Red Hat Inc.