2

So I have an application that allows you to upload documents and images and saves these as byte[] in the database.

(I created an minimal example project that you can download as zip here and import into STS http://dl.dropbox.com/u/2342474/byteMemoryLeak.zip... all you have todo is go to the datasource.groovy and change your db settings)

So the domain object looks something like this:

class Test { 

    byte[] data 

    static constraints = { 
        data nullable: false, maxSize: 1024*1024*40 
    } 
} 

and the controller and views are all generated directly with the generate-all command... nothing changed here...

So now when we start the project we go to the test controller... hit create new... upload a document ... use something thats like 5 - 10 mb... and hit create...

I expect the memory usage to go up while the save() method is execute and then when the show method is called too... but once those are finished loading GC should pick up those objects and throw them away since they are currently not needed... now i used Your Kit Java Profiler to check the memory usage and i can see that there are 3 reference of my byte[] which have weak reference or are unreachable... why is that? shouldnt they have been removed right when the show() method or save() method complete?

Here a screenshot: [memory leak]: https://i.stack.imgur.com/R7KMt.png

Do I have to make special settings for tomcat to run the gc more often?

I am very confused about this and it actually causes a problem in the application that I have in testing right now cause people are uploading a lot of documents to it and the heap memory just gets fuller and fuller and gets almost never cleaned so that i get at some point an out of memory exception... the same actually happens also in the list() method that it loads all the objects and now actually for each object the byte[] is loaded and now in memory and doesnt get cleaned up...

Maybe I am just missing something or doing something wrong... any help would be greatly appreciated...

Thanks Chris

jmj
  • 237,923
  • 42
  • 401
  • 438
  • 2
    +1 for including an example project people can download, great to see some good effort put into your question. No answer from me sorry, but I will be watching this. – David Apr 26 '12 at 23:01

2 Answers2

3

Grails application usually runs with JRE created in server mode which affects how memory works. Basically, when running in "client" mode, then it tries to use less memory and to release it more often, while when running in server mode, JRE tries to use more memory to provide more speed. You can read some discussion here: Real differences between “java -server” and “java -client”

Basically, JRE will allow heap to grow till its limit and only then it will think about freeing memory.

I downloaded your example and started it up, then I uploaded same file multiple times. Memory usage of java process grows like this (for each request: 822mb -> 917mb -> 1.03mb, and then it stops. Next uploads did not increase memory usage and no PermGen space exception was thrown.

So, I think there is no memory leak happening here. What you experiencing is just JRE tries not to run GC until it still can allocate new one (cause generally, running GC is slower then just allocating new memory).

Hope this helps.

Community
  • 1
  • 1
kenota
  • 5,640
  • 1
  • 15
  • 11
  • Well my problem is that i actually have an application in production that just continues to grow and grow the the memory from people uploading files and i guess the gc not cleaning it fast enough... do you know of any jvm options for tuning it? – Christopher Rivera Apr 27 '12 at 15:50
0

You can try using the option -XX:+UseConcMarkSweepGC. This option Collects tenured collection concurrently with the execution of the app. The app is paused for short periods during collection

allthenutsandbolts
  • 1,513
  • 1
  • 13
  • 34