16

I'm currently monitoring my running java application with Visual VM: http://visualvm.java.net/

I'm stressing the memory usage by with -Xmx128m.

When running I see the heap size increasing to 128m (as expected) however the used heap converges to approximately 105m before I run into a java heap space error.

enter image description here

Why are these remaining 20m, not used?

trincot
  • 317,000
  • 35
  • 244
  • 286
Will
  • 2,858
  • 6
  • 33
  • 50
  • Can you include the heap space error you are getting? Perhaps its an issue in permgen? – Paul Whelan May 04 '11 at 10:51
  • 2
    You have multiple heaps, there's "Eden Space", "Survivor Space" and "Tenured Gen". And you have non-heap memory. Maybe there's a filter in VisualVM. And does your application require that 20m? – Thomas Jungblut May 04 '11 at 10:55
  • I'm getting a "java.lang.OutOfMemoryError: Java heap space" error. what do you mean by ".. filter in VisualWM .."? I'm currently reading large files (around 100 MB in total)and build up a map to hold certain information, so I think I need quite some memory. – Will May 04 '11 at 21:02
  • I am not sure what is going on here. Normally you should get OutOfMemoryError when the heap is at 120MB. Can you create Application Snapshot and send it to me? Do you have reproducible test case, you can share? I would like to take a look. – Tomas Hurka May 06 '11 at 18:59

3 Answers3

6

You need to understand a central fact about garbage collector ergonomics:

The costly part of garbage collection is finding and dealing with the objects that are NOT garbage.

This means: as the heap gets close to its maximum capacity, the GC will spend more and more time for less and less return in reclaimed space. If the GC was to try and use every last byte of memory, the net result would be that your JVM would spend more and more time garbage collecting, until ... eventually ... almost no useful work was being done.

To avoid this pathological situation, the JVM monitors the ratio of time is spent GC'ing and doing useful work. When the ratio exceeds a configurable threshold value, the GC raises an OutOfMemoryError ... even though (technically) there is free memory available. This is probably what you are seeing, though the other explanations are equally plausible.

You can change the GC thresholds, generation sizes, etc via JVM options, but it is probably better not to. A better idea is to figure out why your application's memory usage is continually creeping upwards. There are most likely memory leaks ... i.e. a bugs ... in your code that are causing this. Spend your effort finding and fixing those bugs, rather than worrying about why you are not using all of the memory.

(In fact, you are using it ... but not all of the time.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I'm not receiving a GC overhead limit exceeded error, but a java heap space error. – Will May 04 '11 at 20:57
  • Thank you for your help, but as far as I know the scenario you're describing about the GC threshold will throw a OutOfMemoryError: GC overhead limit exceeded. However the error I get is a OutOfMemoryError: java heap space. So I don't think that the porblem lies in the GC running too long and not reclaiming enough memory but rather than I'm running out of heap space, due to whatever reason. – Will May 04 '11 at 22:19
  • The "whatever reason" is most likely a memory leak, and that's what you should focus on tracking down and fixing. The fact that the application doesn't **appear to be** using all of those 128Mb of memory is beside the point. Even if it did, you'd still die from the memory leak ... a bit later on. – Stephen C May 05 '11 at 02:05
  • And if you have good reason to be worried about "wasting" 23Mb of memory due to GC overheads, you've probably chosen the wrong implementation language! – Stephen C May 05 '11 at 02:08
4

Java splits its memory into generations. You can get a heap space error if the tenured generation fills. Normally, they resize dynamically but if you have set a fixed size it won't.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
4

The heap is split up in Young-Generation (Eden-Space, and two Survivor-Spaces of identical size usually called From and To), Old Generation (Tenured) and Permanent Space.

The Xmx/Xms option sets the overall heap size. So a region (with a default size) is actually the Permanent Space - and maybe, we don't know details about your stress test, no objects are actually moved from eden to tenured or permanent, so those regions remain empty while Eden runs out of space.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • I thought the perm gen is stored seperately? – Will May 04 '11 at 21:01
  • @Will - me too, but then I read some articles explaining, that the `-Xmx` parameter tunes the *complete* heap (including PermGen) and other flags like `XX:MaxPermSize` tune the internal heap structure – Andreas Dolk May 05 '11 at 04:30
  • Thx, could you provide me the link of that article? – Will May 05 '11 at 09:32
  • Thanks. According to the article the heap contains the PermGen. So if VisualVm would consider PermGen not as used space (which is not intuitive) my question would be solved. – Will May 09 '11 at 14:46