Talk about jvm’s CompressedClassSpace

  jvm

Order

This article mainly studies the jvm’s CompressedClassSpace

CompressedClassSpace

  • Java8 removes permanent generation, and then class metadata is stored in native memory. its size is unlimited by default and can be limited by-xx: maxmetaaspacesize
  • If–XX:+UseCompressedOops and-xx:+usecomputersedclasspointers (The default is on), UseCompressedOops will use a 32-bit offset to represent the java object reference, while UseCompressedClassPointers will use a 32-bit offset to represent the ClassPointer in the 64-bit process; You can use CompressedClassSpaceSize to set the space size of this block.
  • If pointer compression is turned on, the CompressedClassSpace is allocated in MaxMetaClassSize, that is, MaxMetaClassSize = CompressedClassSpace Size+MetaClassSpace Area (Excluding the CompressedClassSpace) Size

View CompressedClassSpace Size

jcmd pid GC.heap_info

/ # jcmd 1 GC.heap_info
1:
Shenandoah Heap
 524288K total, 144896K committed, 77232K used
 2048 x 256K regions
Status: not cancelled
Reserved region:
 - [0x00000000e0000000, 0x0000000100000000)

 Metaspace       used 45675K, capacity 46867K, committed 47104K, reserved 1091584K
  class space    used 5406K, capacity 5838K, committed 5888K, reserved 1048576K

It can be seen that the entire metaspace uses 45675K, of which the class space uses 5406K, while the metaspace area (excluding the compressed classspace) uses 45675k-5406k = 40269k; The reserved size of the entire metaspace is 1091584K, where the reserved size of class space is 1048576K.

jcmd pid VM.native_memory

/ # jcmd 1 VM.native_memory
1:

Native Memory Tracking:

Total: reserved=2224403KB, committed=238187KB
-                 Java Heap (reserved=524288KB, committed=144896KB)
                            (mmap: reserved=524288KB, committed=144896KB)

-                     Class (reserved=1092940KB, committed=48460KB)
                            (classes #8563)
                            (  instance classes #7988, array classes #575)
                            (malloc=1356KB #20589)
                            (mmap: reserved=1091584KB, committed=47104KB)
                            (  Metadata:   )
                            (    reserved=43008KB, committed=41216KB)
                            (    used=40286KB)
                            (    free=930KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=5888KB)
                            (    used=5407KB)
                            (    free=481KB)
                            (    waste=0KB =0.00%)

-                    Thread (reserved=37130KB, committed=2846KB)
                            (thread #36)
                            (stack: reserved=36961KB, committed=2676KB)
                            (malloc=127KB #189)
                            (arena=42KB #70)

-                      Code (reserved=529360KB, committed=15420KB)
                            (malloc=968KB #4745)
                            (mmap: reserved=528392KB, committed=14452KB)

-                        GC (reserved=21844KB, committed=7724KB)
                            (malloc=5460KB #9644)
                            (mmap: reserved=16384KB, committed=2264KB)

-                  Compiler (reserved=165KB, committed=165KB)
                            (malloc=34KB #455)
                            (arena=131KB #5)

-                  Internal (reserved=3758KB, committed=3758KB)
                            (malloc=1710KB #6582)
                            (mmap: reserved=2048KB, committed=2048KB)

-                     Other (reserved=32KB, committed=32KB)
                            (malloc=32KB #3)

-                    Symbol (reserved=10277KB, committed=10277KB)
                            (malloc=7456KB #225421)
                            (arena=2821KB #1)

-    Native Memory Tracking (reserved=4235KB, committed=4235KB)
                            (malloc=10KB #126)
                            (tracking overhead=4225KB)

-               Arena Chunk (reserved=176KB, committed=176KB)
                            (malloc=176KB)

-                   Logging (reserved=7KB, committed=7KB)
                            (malloc=7KB #264)

-                 Arguments (reserved=18KB, committed=18KB)
                            (malloc=18KB #500)

-                    Module (reserved=165KB, committed=165KB)
                            (malloc=165KB #1708)

-                 Safepoint (reserved=4KB, committed=4KB)
                            (mmap: reserved=4KB, committed=4KB)

-                   Unknown (reserved=4KB, committed=4KB)
                            (mmap: reserved=4KB, committed=4KB)

You can see the class part, the reserved size is 1092940KB, where the reserved size of Metadata is 43008KB and the reserved size of Class space is 1048576KB;. Metadatauses 40286KB and Class space uses 5407KB.

Jmx view

    @GetMapping("/meta")
    public Object getMetaspaceSize(){
        return ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)
                .stream()
                .filter(e -> MemoryType.NON_HEAP == e.getType())
                .filter(e -> e.getName().equals("Metaspace") || e.getName().equals("Compressed Class Space"))
                .map(e -> "name:"+e.getName()+",info:"+e.getUsage())
                .collect(Collectors.toList());
    }

The output is as follows:

/ # curl -i localhost:8080/memory/meta
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 31 Mar 2019 03:06:55 GMT

["name:Metaspace,info:init = 0(0K) used = 46236784(45153K) committed = 47710208(46592K) max = -1(-1K)","name:Compressed Class Space,info:init = 0(0K) used = 5482736(5354K) committed = 6029312(5888K) max = 1073741824(1048576K)"]

It can be seen here that Metaspace has used 45153K in total, of which 5354K has been used in the Compressed Class Space part, and 45153k-5354k = 39799k has been used in the excluded the compressed classspace; The max of Metaspace shown here is -1, where the max value of the Compressed Class Space part is 1048576K, i.e. 1g.

Spring boot application view

/ # curl -i "http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:nonheap"
HTTP/1.1 200
Content-Disposition: inline;filename=f.txt
Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 31 Mar 2019 02:52:51 GMT

{"name":"jvm.memory.used","description":"The amount of used memory","baseUnit":"bytes","measurements":[{"statistic":"VALUE","value":6.4449464E7}],"availableTags":[{"tag":"id","values":["CodeHeap 'non-profiled nmethods'","CodeHeap 'profiled nmethods'","Compressed Class Space","Metaspace","CodeHeap 'non-nmethods'"]}]}

/ # curl -i "http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:nonheap&tag=id:Metaspace"
HTTP/1.1 200
Content-Disposition: inline;filename=f.txt
Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 31 Mar 2019 02:54:56 GMT

{"name":"jvm.memory.used","description":"The amount of used memory","baseUnit":"bytes","measurements":[{"statistic":"VALUE","value":4.7468312E7}],"availableTags":[]}

/ # curl -i "http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:nonheap&tag=id:Compressed%
20Class%20Space"
HTTP/1.1 200
Content-Disposition: inline;filename=f.txt
Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 31 Mar 2019 02:55:18 GMT

{"name":"jvm.memory.used","description":"The amount of used memory","baseUnit":"bytes","measurements":[{"statistic":"VALUE","value":5609952.0}],"availableTags":[]}

Springboot uses micrometer to provide relevant index query function through/actor/metric interface, where Metaspace and Compressed Class Space are in jvm.memory.used
It is implemented based on MemoryPoolMXBean. for details, see micrometer-core-1.1.3-sources.jar! /io/micrometer/core/instrument/binder/jvm/JvmMemoryMetrics.java

Summary

  • Java8 removes permanent generation, and then class metadata is stored in native memory. its size is unlimited by default and can be limited by-xx: maxmetaaspacesize; If–XX:+UseCompressedOops and-xx:+usecomputersedclasspointers (The default is on), UseCompressedOops will use a 32-bit offset to represent the java object reference, while UseCompressedClassPointers will use a 32-bit offset to represent the ClassPointer in the 64-bit process; You can use CompressedClassSpaceSize to set the space size of this block.
  • When pointer compression is turned on, the CompressedClassSpace is allocated in MaxMetaClassSize, that is, MaxMetaClassSize = CompressedClassSpace Size+MetaClassSpace Area (Excluding the CompressedClassSpace) Size
  • There are several ways to view the memory usage of CompressedClassSpace:

    • jcmd pid GC.heap_info(Metaspace is the total part and contains class space, while metaaspace area (excluding the compressed classspace) needs its own calculation, that is, total-class space.)
    • jcmd pid VM.native_memory(The class is the general part, including the meta-aspacearea (excluding the compressed Class Space) and classspace.)
    • Using JMX to get MemoryPoolMXBean with name Metaspace and Compressed Class Space in NON_HEAP type can get the usage of Metaspace and Compressed Class Space (The Metaspace obtained by JMX is the total part, while metaspace area (excluding the compressed classspace) needs its own calculation, that is, total-class space.)
    • If it is a springboot application, it uses micrometer to provide relevant index query function through/actor/metric interface, where Metaspace and Compressed Class Space are in jvm.memory.used

doc