Details
-
Type:
Task
-
Status:
Closed
-
Priority:
Blocker
-
Resolution: Cannot Reproduce
-
Affects Version/s: 1.2 final
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
-
Environment:Using Netbeans profiler to find memory leaks in Groovy Grails web application
Description
Using Netbeans profiler to find memory leaks in Groovy Grails web application. When I select inspect option in the heapwalker shows that StreamCharBuffer object has been retained and it is almost consuming around 80MB for one iteration, which is a huge consumption. Appreciate quick insight into this matter and if a patch for the fix can be given, it would be really great.thanx
Attachments
-
- heapdump-1264082472843.hprof.torrent
- 23/Jan/10 6:20 AM
- 29 kB
- VeenaKaul
-
- Screenshot-jlf - NetBeans IDE 6.7.1.png
- 141 kB
- 22/Jan/10 3:59 AM
Issue Links
| This issue is duplicated by: | ||||
| GRAILS-5747 | Memory leak in org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse |
|
|
|
| This issue relates to: | ||||
| GRAILS-5762 | rendering large data using sitemesh filter leads to double the datasize memory leak..found during stress testing |
|
|
|
| GRAILS-5773 | Add support for excluding uri's from Sitemesh processing in a Grails way (in UrlMappings etc) |
|
|
|
Activity
- All
- Comments
- Work Log
- History
- Activity
- Git Commits
Hi, We are developing a large web services using groovy grails 1.2 environment. After one iteration, i clean up the GC and then inspect using the heapwalker, then i see the following as top 20 retained objects.. Could you please let us know how to fix this or is there any work around for this memory retention ? (P.S. We don't directly use web.util class, but we use some of the open sources which inturn use web.util classes.). HeapDump is 170MB and hence i would not be able to send across the same.
org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse#1 14,649,253
org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse$2#1 14,649,027
org.codehaus.groovy.grails.web.util.StreamCharBuffer#3 14,648,156
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StreamCharBufferSubChunk#2 7,627,432
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#6 7,627,368
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#7 7,627,292
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#5 7,625,143
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#8 7,623,516
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#9 7,623,439
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#10 7,619,243
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#11 7,610,951
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#12 7,594,467
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#13 7,561,599
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#14 7,495,963
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#15 7,364,792
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#6 7,102,547
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#16 7,099,034
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#17 7,098,958
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#7 6,574,569
Does a strong reference to these objects exist? ("Find Nearest GC root" in nb profiler) These objects might just be on the heap, but they aren't GCed yet. I have a feeling that System.gc() doesn't ensure that objects are gc'ed in modern JVMs.
What do you mean with iteration?
Do you have actual problems? Running out of memory, etc?
Hi, I tried tuning as per : http://markmail.org/message/hblkhl3sdngxn3o2 . But still see the huge leak (close 80MB per run). Appreciate your help!
Hi Lari, Thanx for the quick response. We are using the concurrentGC option and profiler shows that memory is being cleaned up. The actual problem we see after around 400 requests(sorry to confuse you with iterations), our app throws "GC Overhead limit exceeded" with server having no free memory.
I shall checkout on the Nearest GC root and get back to you..
One more question: are you testing with "grails prod run-war" or running the war inside an app server like Tomcat. What is your environment and it's settings (JVM vendor&version, JVM options, appserver)?
Hi Lari, I downloaded grails 1.2RC2 source code (as 1.2 final sources are not on the web) and found few items that may lead to memory leak in StreamcharBuffer. Please do go over and let me know your feedback:
1. Hashmap, hashset dereferencing is not done after the element is removed and clear is not called on these.
2. java.io.reader and write objects are not closed . (writer needs to be flushed before the close)
3. reuseBuffer function of class AllocatedBuffer, 'buffer' pointer has to be made null
4. AllocateBUfferReader.Read function, the buffer pointer is not set to null when 'removeAfterReading' flag is set
5. last but not least, many pointers that are pointing to the objects on the heap created using 'new' operator are not set to null after the use.
What do you mean with Standard JVM Options? Can you send the output of "jinfo <tomcat_process_id>" or "jinfo -flags <tomcat_process_id>" command?
Have you been able to reproduce the problem on other servers? Is the server "bare metal" or virtual? What OS?
The Grails 1.2 final sources come with the default download package, see grails-1.2.0/src/java directory in the distribution.
In Java, there is no need to set references to null in those cases. You don't have to free memory in Java. GC takes care of that.
Garbage detection is ordinarily accomplished by defining a set of roots and determining reachability from the roots. An object is reachable if there is some path of references from the roots by which the executing program can access the object. The roots are always accessible to the program. Any objects that are reachable from the roots are considered live. Objects that are not reachable are considered garbage, because they can no longer affect the future course of program execution.
http://www.javaworld.com/javaworld/jw-08-1996/jw-08-gc.html?page=2
Did you check what the "Find Nearest GC Root" shows for StreamCharBuffer instances on your heap? Are they "live" or "garbage"?
Garbage detection is ordinarily accomplished by defining a set of roots and determining reachability from the roots. An object is reachable if there is some path of references from the roots by which the executing program can access the object. The roots are always accessible to the program. Any objects that are reachable from the roots are considered live. Objects that are not reachable are considered garbage, because they can no longer affect the future course of program execution.http://www.javaworld.com/javaworld/jw-08-1996/jw-08-gc.html?page=2 Did you check what the "Find Nearest GC Root" shows for StreamCharBuffer instances on your heap? Are they "live" or "garbage"?
JVM version is 14.1-b02
Java System Properties:
java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = /usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/amd64
java.vm.version = 14.1-b02
shared.loader =
java.vm.vendor = Sun Microsystems Inc.
java.vendor.url = http://java.sun.com/
path.separator = :
tomcat.util.buf.StringCache.byte.enabled = true
java.util.logging.config.file = /usr/local/tomcat/conf/logging.properties
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg = sun.io
sun.java.launcher = SUN_STANDARD
user.country = IN
sun.os.patch.level = unknown
java.vm.specification.name = Java Virtual Machine Specification
user.dir = /usr/local/tomcat/bin
java.runtime.version = 1.6.0_15-b03
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.endorsed.dirs = /usr/local/tomcat/endorsed
os.arch = amd64
java.io.tmpdir = /usr/local/tomcat/temp
line.separator =
java.vm.specification.vendor = Sun Microsystems Inc.
java.naming.factory.url.pkgs = org.apache.naming
java.util.logging.manager = org.apache.juli.ClassLoaderLogManager
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/amd64/server:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/amd64:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/../lib/amd64:/usr/java/packages/lib/amd64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 50.0
sun.management.compiler = HotSpot 64-Bit Server Compiler
os.version = 2.6.31-17-generic
user.home = /home/sandbox
catalina.useNaming = true
user.timezone = Asia/Kolkata
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.6
catalina.home = /usr/local/tomcat
java.class.path = :/usr/local/tomcat/bin/bootstrap.jar
user.name = sandbox
java.naming.factory.initial = org.apache.naming.java.javaURLContextFactory
package.definition = sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
java.vm.specification.version = 1.0
java.home = /usr/lib/jvm/java-6-sun-1.6.0.15/jre
sun.arch.data.model = 64
user.language = en
java.specification.vendor = Sun Microsystems Inc.
java.vm.info = mixed mode
java.version = 1.6.0_15
java.ext.dirs = /usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/alt-rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.15/jre/classes:/lib/jfluid-server.jar:/lib/jfluid-server-15.jar
server.loader =
java.vendor = Sun Microsystems Inc.
catalina.base = /usr/local/tomcat
file.separator = /
java.vendor.url.bug = http://java.sun.com/cgi-bin/bugreport.cgi
common.loader = ${catalina.home}/lib,${catalina.home}/lib/*.jar
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
package.access = sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.,sun.beans.
sun.cpu.isalist =
VM Flags:
-Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Xmx2048m -Xms512m -XX:PermSize=512m -XX:MaxPermSize=1024m -Xverify:none -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy -XX:SurvivorRatio=32 -XX:TargetSurvivorRatio=80 -XX:MaxTenuringThreshold=77 -XX:+AggressiveOpts -XX:-UseConcMarkSweepGC -XX:-UseGCOverheadLimit -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -agentpath:/lib/deployed/jdk15/linux-amd64/libprofilerinterface.so=/lib,5140 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
We have a dedicated server running on ubuntu(multi-processor with 8GB RAM) and apart from that we have been able to reproduce this problem on other development team servers too. Running IBM's hprof shows that 80% of leaks are from Sitemesh and StreamCharBuffer classes. These objects are 'live'.
I'd like to know if you could try "Find Nearest GC Root" to find out what is keeping references to these instances.
Lari, I used hprof and then realized that the StreamCharBuffer leak is happening is thru Sitemesh code. Basically when we render huge data, sitemesh leaks 2*datasize. I did checkout this issue with opensymphony, where someone has mentioned similar problem. So, you can close this bug and keep another issue reported by me on SiteMesh open.
There is Grails specific integration to Sitemesh in Grails 1.2 so I think it's worth investigating the case further. The Grails specific integration to Sitemesh is active when "grails.views.gsp.sitemesh.preprocess" Config.groovy setting is true or undefined (when gsp's are compiled).
What is the "gc root" that is holding references to these instances?
Usually these gc roots are static fields, ThreadLocals, objects in servletContext, spring context etc.. I'm still interested to see what the "nearest gc root" is. Have you tried to find it?
If there is no gc root, these object instances are just "garbage" which hasn't been collected yet.
I'd like to see the full thread dump (stacktraces of all threads) when OutOfMemoryError occurs.
In some cases deadlocks between threads might cause request processing threads to lock up and that would cause high memory consumption. Have you checked the thread dump of the Tomcat process? In unix "kill -3 <tomcat_process_id>" will dump the stacktraces of all threads to standard output, which goes to catalina.out in default tomcat configuration. The JVM option -XX:+HeapDumpOnOutOfMemoryError should do the heap dump when OutOfMemoryError occurs and print out the thread dump to catalina.out . Add this option and remove netbeans profiler (agentpath JVM option) from Tomcat.
If -XX:+HeapDumpOnOutOfMemoryError doesn't print the full stack traces of all threads automaticly, try -XX:OnOutOfMemoryError="kill -3 %p" option. You can analyze thread dumps with TDA, https://tda.dev.java.net/ .
It's also possibile that there is a eternal loop somewhere in gsp (some loop condition never ending or a template/taglib calling itself recursively infinitely). The thread dump would reveal this kind of problem.
btw. You'd save a lot of memory on 64-bit Ubuntu by running a 32-bit JVM (sudo apt-get install lib32nss-mdns ia32-libs; then install binary directly from java.sun.com) or running the recent 64-bit JVM 1.6.0_18 with the "-XX:+UseCompressedOops" option. This would not fix the possible memory leak problem, but it consumes a lot less OS memory. We run grails apps on 32-bit JVM on 64-bit Ubuntu since -XX:+UseCompressedOops wasn't very stable earlier. It might be ok in 1.6.0_18 .
I did find some memory consumption problems in Grails Sitemesh integration, but I didn't find memory leaks. I'm fixing the memory consumption problem (preferSubChunkWhenWritingToOtherBuffer isn't used when it should be, the reason is that capture* tags were moved from 'g' namespace to 'sitemesh' namespace, but some code in GroovyPage.resolvePreferSubChunk wasn't updated).
Please test with 1.2.1.SNAPSHOT build: http://hudson.grails.org/job/grails_core_1.2.x/ws/grails/dist/grails-1.2.1.SNAPSHOT.zip
The memory consumption should be lower now (about half per each request). It doesn't fix any leaks since I didn't find any memory leak.
VeenaKaul, I'm still interested to see what the "nearest gc root" is in your case.
Lari, in mycase, PrinterWriter in Sitemesh code was one of the caller who is leading to memory leaks in StreamCharBuffer. But almost all the classes in Web\Utils class heavily use StreamCharBuffer and they all lead to heavy leak.
Just to check on it, in GrailsPrintWriter file I replaced SteamCharBuffer with String and I could see that StreamCharBuffer leak with GrailsPrintWriter root disappeared.
Our heapdump is very huge(over 150 MB). Otherwise I would have definitely sent it across. This particular problem in Grails may become a barrier for an enterprise application to use. I sincerely appreciate any kind of improvement done in StreamCharBuffer to fix the memory leaks. Thanx.
We shall try out the latest snapshot and get back to you in couple of hours.
Leaking is different than consuming memory. I consider leaking in web apps as holding/gathering references to objects that shouldn't be referenced outside request processing. In those cases objects don't get GCed and cause the memory consumption to slowly grow until the app crashes (OutOfMemoryError).
What is your use case? Is it a normal web app? What kind of views/layouts?
we are working on a federated websearch and we render all the results in a single page....
1. Observation: Rendering code that is using lot of Writer Objects in StreamCharBuffer does not call removeConnections of StreamCharBuffer after the use. Do you think this may fill the heap ? If so, you need to inform the developer who is using StreamCharBuffer.
Hi Lari, Below is the observation on 1.2.1.SNAPSHOT. SiteMeshRelated leaks have disappeared in this version. But StreamCharBuffer leaks still exist. I will also give the callstack information on this shortly
20 Retained Size
org.codehaus.groovy.grails.web.util.StreamCharBuffer#3 14,531,020
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StreamCharBufferSubChunk#2 7,535,346
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#15 7,535,282
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#27 7,535,206
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#11 7,533,057
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#28 7,531,430
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#29 7,531,353
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#30 7,527,157
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#31 7,518,865
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#32 7,502,381
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#33 7,469,514
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#26 7,469,437
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#34 7,338,266
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#12 7,076,021
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#35 7,072,508
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#36 7,072,432
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#13 6,548,043
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#37 6,546,260
org.codehaus.groovy.grails.web.util.StreamCharBuffer$StringChunk#14 6,546,183
org.codehaus.groovy.grails.web.util.StreamCharBuffer$CharBufferChunk#38 6,544,238
Hi VeenaKaul could you try the 1.3.x snapshot build: http://hudson.grails.org/job/grails_core/lastSuccessfulBuild/artifact/grails/dist/grails-1.3.0.BUILD-SNAPSHOT.zip
As it has the same fix in it
And VeenaKaul like Lari has said multiple times before can you please, please post the GC roots or an example application that reproduces the problem. Otherwise it is hard for us to reproduce
BUILD FAILED
/home/manish/temp/grails-1.3.0.BUILD-SNAPSHOT/ant/build/bundle.xml:114: The following error occurred while executing this line:
/home/manish/temp/grails-1.3.0.BUILD-SNAPSHOT/ant/build/bundle.xml:87: The following error occurred while executing this line:
/home/manish/temp/grails-1.3.0.BUILD-SNAPSHOT/ant/build/bundle.xml:99: Error while expanding /home/manish/temp/grails-1.3.0.BUILD-SNAPSHOT/bundlor/bundlor-1.0.0.RELEASE.zip
java.io.FileNotFoundException: /home/manish/temp/grails-1.3.0.BUILD-SNAPSHOT/bundlor/bundlor-1.0.0.RELEASE.zip (No such file or directory)
Graeme, Need a clarification: When we call render function from our controller, does the control goto metaclass\RenderDynamicMethod.java and then to GSPPrinterWriter.java getInstance() function. If you could give a hint on the control flow for Render function, it would be great
Moved GroovyPageOutputStack instance from it's own ThreadLocal to RequestAttributes
http://github.com/grails/grails/commit/282333b2a6e382d3a5e61dafe2013db18a5977d3
VeenaKaul with the snapshot you don't need to build it yourself, it is already built. That is the whole point of providing you with the snapshot download. Just set your GRAILS_HOME to where you unzipped it to and run the normal grails commands to test your application
I understand that snapshots for using the grails library, not to work on the code....As part of our job, we are also looking into grails code on how to get away with memory leaks.
could you please upload the latest version of the snapshot as you have change Moved GroovyPageOutputStack instance from it's own ThreadLocal to RequestAttributes
Latest 1.2.x SNAPSHOT build: http://hudson.grails.org/job/grails_core_1.2.x/ws/grails/dist/grails-1.2.1.SNAPSHOT.zip , includes the change: http://hudson.grails.org/job/grails_core_1.2.x/62/
The only problem is "gc root references" (usually statics, thread locals, fields inside singletons etc) if they are kept after the request processing has ended. During request processing it doesn't make much sense to clear references.
Did you take the heap dump when there was no activity on the server? It's a leak only if gc roots are referering these instances after request processing has ended.
–
If you are creating extremely big responses with GSP, you should bypass sitemesh totally since the output is always buffered when sitemesh is used. By default, the content of <head> and <body> tags are also "captured" and buffered (using StreamCharBuffer), but you can easily bypass that by creating the "<body>" tag at runtime so that the Sitemesh preprocessing in GSP compilation doesn't get used. (in gsp create body tag dynamicly, for example <<%= 'body' %>>). Maybe we should add a GSP page directive to specify that sitemesh preprocessing could be disabled per gsp file.
Currently you have to edit WEB-INF/sitemesh.xml to bypass sitemesh for a text/html contenttype with a certain url. I'm not sure if these examples help: http://forums.atlassian.com/message.jspa?messageID=257321008 . It would be nice if there was a Grails way to bypass sitemesh for a certain url.
All grails output is buffered, but the "top level" buffer (GSPResponseWriter) is flushed automaticly (StreamCharBuffer in "connected" mode). It's possible to turn off this level with -DGSPResponseWriter.enableBuffering=false System property .
See GRAILS-5770 , there's instructions to exclude a certain uri from sitemesh processing. If you're creating huge responses with GSP (which aren't webpages), for example CSV downloads etc. Then you should disable sitemesh for the uri and possibly disable sitemesh preprocessing for the view that creates the response (only required if the response is html inside a body).
I've added a new feature request GRAILS-5773 . There is a manual workaround explained in GRAILS-5773 and GRAILS-5770 .
Lari, yes I did take the heapdump once the task is over and that too after Running GC from the profiler. So, that also means that there are strong references held for these pointers.
I did disable the use of SiteMesh and even in that case there are N number of memory leaks in SteamCharBuffer. I'm trying to develop a simple webapp which renders huge data, which should be able to demonstrate the memory leak in StreamCharBuffer.
It doesn't make sense to nullify internal references, the problem is the reference pointing to the StreamCharBuffer. In the screenshot you send, it was hanging on a GrailsContentBufferingResponse which is in a ThreadLocal (this is normal during request processing), but it should be cleared after the request processing finishes.
I'd like to see the full thread dump (stacktraces of all threads) when the heap dump was taken.
In unix "kill -3 <tomcat_process_id>" (it doesn't "kill" the process) will dump the stacktraces of all threads to standard output , which goes to catalina.out in default tomcat configuration. More information in my previous comment about threadumps.
Thread dumps are plain text (stack traces of all threads) so could you please send it to my email address (you'll find the address in my JIRA profile) as a txt file attachment?
There might be some request handling threads blocked (deadlocks, waiting for IO, db-connection, etc.) and that would show up in the thread dump.
Yes there is, you can disable Sitemesh and also most of the buffering. Instructions in this jira issue: GRAILS-5773 . If you don't want to use sitemesh at all, disable it with these instructions and set "grails.views.gsp.sitemesh.preprocess = false" in Config.groovy. You could also disable response buffering in GSPResponseWriter by setting the system property GSPResponseWriter.enableBuffering=false (for tomcat add -DGSPResponseWriter.enableBuffering=false to JAVA_OPTS in catalina.sh) . I don't think you should need to do this if you have a typical webapp.
I couldn't download the heapdump by torrent, no seeds were found (I think your tracking server address was missing from the torrent file).
Could you rather send a threaddump (just a couple of hundreds of lines of text) at the time you made the heapdump by email? A typical thread dump takes 100-200 kB.
I suspect the memory leak is caused by request processing threads getting blocked. We could easily check that condition from the thread dump. I think we cannot get further with this investigation without the threaddump. Please read my earlier comments about how to get a threaddump.
Lati, We have been able to disable the SiteMess preprocessing and get away with Sitemesh and StreamCharBuffer related memory leaks in grails 1.1.1.
With grails 1.2 we are afraid to move, as StreamCharBuffer has been used outside SiteMesh preprocessing too. Is there anyway to move to grails 1.2 version without using Streamcharbuffer ?
Please send the threaddump at the time you made the heapdump. The threaddump is very small just a couple of 100k's max. I'd like to check if there is hanging request threads.
You could also send the heapdump if you like. I wasn't able to download the torrent earlier (tracking server information was missing). Please upload the dump to some filesharing service like http://www.filedropper.com/ etc. and send the link to me by email (don't post it in public). Please compress the dump first with http://www.7-zip.org/ etc. (gzip, 7z or zip). Please notice that a heapdump might include sensitive information like passwords etc. Don't send it if it does contain sensitive information.
—
Why would you want to move away from StreamCharBuffer? I don't think StreamCharBuffer itself causes memory leaks. I'd appreciate the feedback if you could prove (provide a test case / heapdumps/threaddumps) that it does. The source of the memory leak might be elsewhere even if StreamCharBuffer instances pile up in the heap.
Please provide the information I've asked for a several times. Patches and test cases showing the problem are always welcome! This is an opensource project.
I've reviewed the StreamCharBuffer code once more and I got an idea of a performance improvement. I found a small source of a temporary leak in a special case (which might not exist anywhere), but I don't think it's the problem in your case.
Objects show up in the heap until they are GCed, this is normal behaviour in the JVM. All output from Grails/GSP gets buffered through StreamCharBuffers in multiple levels and the amount of total temporary "consumption" is quite large. Usually this isn't a problem.
Here's some explanations about StreamCharBuffer: http://markmail.org/message/hblkhl3sdngxn3o2 . You can tune it to use less memory, but I haven't noticed that it would improve throughput performance.
Some question to you:
What is your actual problem? Is your app "leaking" memory (is there a strong reference to the StreamCharBuffer instance)? Do you have a performance problem?
Can you provide a test app that shows the problem?