java memory leak, visualvm showing wrong data

2019-04-29 19:39发布

问题:

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

回答1:

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).



回答2:

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.



回答3:

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