Search code examples
javamemory-managementjvmjstatjcmd

NMT Class committed vs Jstat Compressed Class Space


I'm investigating the OutOfMemoryError: Compressed Class Space issue. I think, that I found my root cause and solution for it (JAXBContext.newInstance() called by Hibernate Validator method: buildValidatorFactory after every submitted action by users) but during my research I've noticed one confusing thing.

I've tried to run jcmd VM.native_memory and jstat -gc to track Class committed size and CCSU (Compressed Class Space Usage):

d:\experiments>jcmd 59692 VM.native_memory summary
Native Memory Tracking:

Total: reserved=10039335KB, committed=889895KB
-                 Java Heap (reserved=8353792KB, committed=522240KB)
                            (mmap: reserved=8353792KB, committed=522240KB)

-                     Class (reserved=1072460KB, **committed=24268KB**)
                            (classes #2518)
                            (malloc=9548KB #2393)
                            (mmap: reserved=1062912KB, committed=14720KB)

and

d:\experiments>jstat -gc 59692 2s
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
21504,0 21504,0  0,0    0,0   131072,0 56218,7   139264,0    7755,5   14976,0 14318,5 1920,0 1721,7      2    0,012   1      0,036   -          -    0,048

I expected that there is no major difference between "Class committed" metric in NMT and CCSU in jstat, but jstat shows about only 1,72 MB of used memory against Class Committed which is over 24 MB. So I generated GC.class_stats statistic and it shows that KlassBytes is about 1738616 B -> 1,739 MB - so it approximettely the same value as jstat shows in CCSU. Also I found out that the rest of metadata like Methods, Constants etc.) occupied about 14,44 MB (this is approximetly the same as value in mmap: committed=14720KB - but I don't know what is this number).

So where is the rest of it? What exactly is the number presented by NMT?


Solution

  • Class section in Native Memory Tracking report shows the aggregated numbers for both Metaspace and Compressed Class Space. The difference between Metaspace and Compressed Class Space is explained here.

    Metaspace vs. Compressed Class Space

    The slide from the Memory Footprint of a Java Process presentation


    jstat metrics MC, MU, CCSC and CCSU stand for

    • Metaspace Capacity
    • Metaspace Used
    • Compressed Class Space Capacity
    • Compressed Class Space Used

    The relation between Committed, Capacity and Used is explained in this answer.

    So, the Class Committed as shown by Native Memory Tracking is related to jstat metrics with the following inequality:

    Class Committed >= MC + CCSC >= MU + CCSU
    

    However, the difference between them can be arbitrary large.


    Since JDK 10, Native Memory Tracking report shows the detailed breaks down of Class section:

    -     Class (reserved=1073841KB, committed=28593KB)
                (classes #3967)
                (  instance classes #3694, array classes #273)
                (malloc=689KB #9228) 
                (mmap: reserved=1073152KB, committed=27904KB) 
                (  Metadata:   )
                (    reserved=24576KB, committed=24576KB)
                (    used=24131KB)
                (    free=445KB)
                (    waste=0KB =0.00%)
                (  Class space:)
                (    reserved=1048576KB, committed=3328KB)
                (    used=3003KB)
                (    free=325KB)
                (    waste=0KB =0.00%)