6

I've a java application running, after few hours it fulfills memory. I've tried to detect memory leak with visualvm but it shows wrong data (have no idea how that can happen).

In the screenshot you can see task manager showing memory usage of 700Mb and visualvm showing 225...

Does anyone know whats going on here?

Regards

enter image description here

vach
  • 10,571
  • 12
  • 68
  • 106
  • 2
    if memory leak is happening set -XX:PermSize=256m -XX:MaxPermSize=256m as VM arguments – lakshman Jan 27 '14 at 09:04
  • @Vach This does not look like a memory leak... – assylias Jan 27 '14 at 09:09
  • @lakshman this does not solve the PermGenSize memory leak at all, it just delays the actual problem. A better suggestion would be to propose a framework which actually is able to unload classes if they aren't needed/used anymore. This however requires intelligent class-loading and further a rather strict handling (especially of singletons and enums) – Roman Vottner Jan 27 '14 at 09:11
  • OFFTOP: There is a possibility to zoom in the image ? – Tomasz Waszczyk Jan 27 '14 at 09:13
  • @MrPhi just right click on it and open image in new tab – vach Jan 28 '14 at 09:31
  • @assylias I'll describe its behavior, this is a side product by vmware called gemfire, when i start it, at first everything works as it should be, but the memory allocation shown in task manager increases all the time, in few hours even my mouse will start to glinch and i'll be forced to kill the process... I'm using Dell Precision Workstation and this is not a weak machine... – vach Jan 28 '14 at 09:34
  • I'd like to run it giving my java vm parameters, but I only have .bat file which runs java program itself and closes... Anyway even if i give those parameters as @RomanVottner said this is not a solution, I still do think that this is a memory leak... – vach Jan 28 '14 at 09:36
  • 1
    @Vach I didn't mention these parameters at all - I just commented that they won't solve the problem instead of just delaying it. In my opinion the best way to spot a memory leak is to reduce the given memory given the parameters presented by lakshman to a bare minimum and then use a profiler to produce heapdumps which you then can start to analyze in more detail. Why you should reduce the memory? As this will force GC sooner and your problem will probably occur earlier. Moreover the heapdumps will not occupy to much disk-space too. – Roman Vottner Jan 28 '14 at 09:47
  • @Vach It is weird that visual vm would give wrong information. It could be a JVM issue (you could try to upgrade to a recent version if it is not the case already) or it may be due to your virtual environment (you could try running your application on a physical machine to check if you get the same behaviour). – assylias Jan 28 '14 at 10:35

3 Answers3

4

Beware that your OS is only aware of the total amount of memory java has reserved over the time (and java will not return that amount of memory easily AFAIK). However java may not be using all that memory at a given moment, so you can see differences between those two numbers.

For example, if you launch your program like this

java -Xmx512m -Xms256m ...

Then your JVM will take 256 MB as soon as it starts (and the OS will tell you so, more or less). However, if you open your memory peek tool (be it visualvm, jconsole, etc.), it may show that you are using less than that (it is just you have not needed to use the whole of your reserved heap).

Jorge_B
  • 9,712
  • 2
  • 17
  • 22
  • ok "it can show that I'm using less than that" but if I run the given java app using -Xmx512 does that mean that 512 is the maximum memory defined for that app, and task manager theoretically should not show more allocation that 512? or I didn't understand something? – vach Jan 28 '14 at 09:29
  • 1
    That will be the max heap size, but there are other regions taking more OS space (appart of the space the JVM needs itself to put its own code and variables in memory). Take it as an orientation (but quite useful to set your JVM limits) – Jorge_B Jan 28 '14 at 09:52
3

What Java gets it doesn't return. Allocating memory takes quite a lot of effort, so Java doesn't usually return any of the memory the system ever granted it. So if your program ever used 760 MB RAM this is what it sticks with.

And then there are two other factors that play an important role. The heap size is only the amount of memory your program uses or can use. But between your program and the OS is the Java-VM which might take a good bit of memory as well. The task manager shows you the amount of memory that is used by your program plus the vm.

The other factor is memory fragmentation. Some data structures (e.g. arrays) have to be in a consecutive chunk of the memory. array[i+1] has to be in the memory slot after array[i]. This now means that if you have e.g. 10 MB memory allocated, and the the middle 2 MB memory are used and you want to create an 6 MB array the Java-VM has to allocate new memory, so it can fit the array in one piece. This increases the memory usage in the task manager to go up, but not the heap size, since the heap size only shows actually used memory.

Dakkaron
  • 5,930
  • 2
  • 36
  • 51
  • 3
    actually, the GC takes care of "defragmentation" issues like you've described by re-locating the memory on cleaning and freeing unused objects. – Roman Vottner Jan 27 '14 at 09:32
  • 1
    Alright, makes sense. Well, it probably will only do so when there is a GC run, which might not be at the same time as the allocations. Especially because there is no hard standard about when the GC runs. – Dakkaron Jan 27 '14 at 09:37
2

Memory spaces in Java are defined by 3 metrics: used, available, max available (see JMX values). Size you see is available size and not max available, that is probably already allocated. Again you should also show non heap memory (usually lesser than heap, but you should have setup it differently) To be more precise you should post your JVM startup settings.

PS: looking at your memory profile I can't see any leak: I can see JVM shrinking heap size because it is not used at all

  • Well If you look at visalvm you dont see any leak, what about task manager? – vach Jan 28 '14 at 10:54
  • In task manager you can see allocated memory by process. JVM request to OS memory for its activity based on java euristics and jvm settings even if there are no object in memory. Requesting new memory to OS is expensive and JVM avoid it if it is possible. Post your JVM settings to have a final solution to your question. – SpyGlassTools.com Jan 28 '14 at 11:52