Jmap heap dump, does it include young generation?
Asked Answered
S

1

5

Quick question

Does the jmap heap dump include only the old generation, or also the young generation ?


Long explanation

I have 2 heap dump (jmap -heap:format=b 9999) :

  • one of my server with no load (no HTTP request)
  • one while working 50% CPU, a high load (benchmarking)

Now, the first dump shows a heap size bigger than the second (which I thought was weird).

Could that be because the Young generation (at high load) is changing often because the Garbage collector is running often (yes, the JVM is almost full) ? Old generation is full at 99%, I've noticed the young generation space usage vary a lot.

So that would mean that I made the second dump right after the GC did his job, this is why its size is smaller. Am I right ?

Additionnal informations :

Java args :

-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m
Stralsund answered 19/5, 2011 at 11:47 Comment(0)
A
10

Quick Answer

Both - The Heap is made up of the Young and Old Generation. So when you take a heap dump, the contents contains both. The Stats of the heap dump should be seperated. Try removing the binary portion of your command and look at it in plain text. You will see a summary of your configuration, and then a break down of each generation. On the flip side, a -histo would just show all objects on the heap with no distinction

Long Answer

It could be that a garbage collection had just finished for the 2nd process. Or the opposite, the first process may not have had a full collection in a while and was sitting at higher memory. Was this application/server just restarted when you took the capture? If you look at an idle process using a tool like jvisualvm, you will see the memory allocation graphs move up and down even though your process isn't doing any work. This is just the JVM doing its own thing.

Typically your Full GC should kick off well before it reaches a 99% mark in the Old Gen. The JVM will decide when to run the full GC. Your Young Gen will fluctuate alot as this is where objects are created/removed the fastest. There will be many partial GC's done to clean out the young gen before a full GC get run. The difference between the two will mean a pause in your JVM activity. Seeing a partial GC will not hurt your application. But the pause times of a full GC will stop your application while it runs. So you will want to minimize those the best you can.

If you are looking for memory leaks or just profiling to see how your application(s) gc is working, I would recommend using the startup flags to print the garbage collection stats.

-XX:+PrintGCDetails -verbose:gc -Xloggc:/log/path/gc.log

run your program for a while and then load the captured log in a tool to help visualize the results. I personally use the Garbage Collection and Memory Visualizer offered in the IBM Support Assistant Workbench. It will provide you with a summary of the captured garbage collection stats as well as a dynamic graph which you can use to see how the memory in your application has been behaving. This will not give you what objects were on your heap.

At problem times in your application, if you can live with a pause, I would modify your jmap command to do the following

jmap -dump:format=b,file=/file/location/dump.hprof <pid>

Using a Tool like MAT, you will be able to see all of the objects, leak suspects, and various other stats about the generations, references of the heap.

Edit For Tuning discussion

Based on your start-up parameters there are a few things you can try

  • Set your -Xms equal to the same value as your -Xmx. By doing this the JVM doesn't have to spend time allocating more heap. If you expect your application to take 4gb, then give it all right away
  • Depending on the number of processors on the system you are running this application you can set the flag for -XX:ParallelGCThreads=##.
  • I havent tried this one but the documentation shows a parameter for -XX:+UseParallelOldGC which shows some promise to reduce time of old GC collection.
  • Try changing your new generation size to 1/4 of the Heap. (1024 instead of 64) This could be forcing too much to the old generation. The default size is around 30%, you have your application configured to use around 2% for young gen. Though you have no max size configured, I worry that too much data would be moved to old gen because the new gen is too small to handle all of the requests. Thus you have to perform more full (paused) GC's in order to clean up the memory.

I do believe overall if you are allocating this much memory so fast, then it could be a generation problem where the memory is allocated to the Old generation prematurely. If a tweak to your new gen size doesn't work, then you need to either add more heap via the -Xmx configuration, or take a step back and find exactly what is holding onto the memory. The MAT tool which we discussed earlier can show you the references holding onto the objects in memory. I would recommend trying bullet points 1 & 4 first. This will be trial and error for you to get the right values

Alpers answered 19/5, 2011 at 12:49 Comment(17)
Thanks, that is a complete answer. Quick precision : I did a jmap dump and anaylyzed it with MAT (that's what I meant in my question) and i also got the "non-binary" stats of the JVM with jmap -heap (99% full old gen). I wish I could do a heap dump of just the old generation, because I would like to compare over time the memory size of some objects (a memory cache) but because of the Young being GC often, I can get a big or smaller size on several following dumps... so it's difficult to compare. I'll try enabling GC stats though.Stralsund
Additionally, is that possible to read the GC log like a text file ? (i.e., not use a complex tool)Stralsund
yeah you can read it, just plain text. but trust me from experience, once you stare at it for a while a 3rd party tool will start to look good to you. The tool only helps summarize the data for youAlpers
in the 99% captures (looking in MAT) were there any leak suspects? or when looking at the object breakdown, any that stood out as having more instances then needed?Alpers
The problem doesn't seem to be a memory leak, it's just the sessions, the cache... They are just to big and need to be refactored. The IBM tool you are mentionning is just too difficult to get :p. I need to register at IBM and download a whole bunch of tools I don't want... That's why I'd rather use something else.Stralsund
ah ok. So looks like you will need to throw more heap (-Xmx/-Xms) at your application. If your cache sizes are getting big (and you have the money for it) offloading the Cache to something like BigMemory would be a nice optionAlpers
Oh I've got a full GC every 8 seconds (which last 4 seconds...). Are you sure when the Full GC is running, the JVM is completely stopped ? That would be a big problem...Stralsund
yeah it does pause the JVM to do the full collectionAlpers
do you mind posting your start-up parameters in your original question and which JVM version you are running. I can see if there is anything which you could tweakAlpers
Also, Here is a GC viewer easier to get then the IBM one i mentioned earlier. tagtraum.com/gcviewer.html See what it tells you about your pause times, and throughputsAlpers
Yes I'll try the alternate GC viewer thanks. I'll update the question.Stralsund
i made an edit to my post. see Edit For Tuning discussion. I dont see alot of tweaking options that will help your Full GC problems. A profile would be more useful at this pointAlpers
though the more i think about it, the tweak to the NewSize parameter would make senseAlpers
Thanks for the tweaking infos ! Last thing : do you have a link to the explanation of how the Full GC works (by pausing all the threads) ? I can't find it, and I need a reference to the official documentation in my docs... thanksStralsund
My bad, I finally found it... oracle.com/technetwork/java/javase/…. Thanks!Stralsund
oracle.com/technetwork/java/javase/gc-tuning-6-140523.htm Talks about pause times. Will find the other article talking about young vs old gen cleanupAlpers
Both will pause, just that the Old Gen takes alot longer. Look in the GC log which you enabled. you can see the pause times for everything there. In the app I am working on now, a young gen clean-up takes 0.1seconds, where a full GC (on old gen) is 5-7 seconds. so obviously it is better for your users to have many 0.1 second pauses then having the longer full gc'sAlpers

© 2022 - 2024 — McMap. All rights reserved.