Разговор о CompressedClassSpace jvm

Java

последовательность

В этой статье в основном изучается CompressedClassSpace jvm.

CompressedClassSpace

  • В Java8 убрана постоянная генерация, а метаданные класса хранятся в нативной памяти, размер по умолчанию не ограничен, что можно ограничить параметром -XX:MaxMetaspaceSize.
  • Если -XX:+UseCompressedOops и -XX:+UseCompressedClassesPointers(默认是开启), UseCompressedOops будет использовать 32-битное смещение для представления ссылки на объект Java, а UseCompressedClassPointers будет использовать 32-битное смещение для представления указателя класса в 64-битном процессе; вы можете использовать CompressedClassSpaceSize для установки размера пространства этот блок
  • Если сжатие указателя включено, CompressedClassSpace размещается в MaxMetaspaceSize, то есть MaxMetaspaceSize = размер пространства сжатого класса + размер области метапространства (исключая пространство сжатого класса)

Просмотр размера CompressedClassSpace

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

Видно, что все метапространство использует 45675 КБ, из которых пространство классов использует 5406 КБ, а область метапространства (за исключением сжатого пространства классов) использует 45675 КБ-5406 КБ = 40269 КБ; зарезервированный размер всего метапространства составляет 1091 584 КБ, из которых зарезервированный размер пространства класса 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)

Вы можете видеть часть класса, зарезервированный размер составляет 1092940 КБ, из которых зарезервированный размер метаданных составляет 43008 КБ, а зарезервированный размер пространства класса составляет 1048576 КБ; метаданные используют 40286 КБ, а пространство класса использует 5407 КБ.

jmxView

    @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());
    }

Результат выглядит следующим образом:

/ # 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)"]

Здесь вы можете видеть, что метапространство использует в общей сложности 45153 КБ, из которых часть пространства сжатого класса использует 5354 КБ, в то время как область метапространства (исключая пространство сжатого класса) использует 45153 КБ-5354 КБ = 39799 КБ; и максимальное значение метапространства, показанное здесь, равно -1. , из которых Compressed Максимальное значение части Class Space составляет 1048576K или 1G.

Вид приложения Spring Boot

/ # 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 использует микрометр для предоставления связанных функций запроса индикатора через интерфейс /actuator/metrics, из которых Metaspace и Compressed Class Space находятся в метрике jvm.memory.used. Он реализован на основе MemoryPoolMXBean, подробности см. в micrometer-core-1.1.3-sources.jar!/io/micrometer/core/instrument/binder/jvm/JvmMemoryMetrics.java

резюме

  • Java8 удаляет постоянную генерацию, а затем метаданные класса сохраняются в собственной памяти Размер по умолчанию не ограничен и может быть ограничен -XX:MaxMetaspaceSize; если -XX:+UseCompressedOops и -XX:+UseCompressedClassesPointers(默认是开启), UseCompressedOops будет использовать 32-битное смещение для представления ссылки на объект Java, а UseCompressedClassPointers будет использовать 32-битное смещение для представления указателя класса в 64-битном процессе; вы можете использовать CompressedClassSpaceSize для установки размера пространства этот блок
  • Когда сжатие указателя включено, CompressedClassSpace выделяется в MaxMetaspaceSize, то есть MaxMetaspaceSize = размер сжатого пространства класса + размер области метапространства (исключая пространство сжатого класса)
  • Существует несколько способов просмотра использования памяти CompressedClassSpace:
    • jcmd pid GC.heap_info(Metaspace为总的部分,包含了class space,而Metaspace area (excluding the Compressed Class Space)需要自己计算即total-class space)
    • jcmd pid VM.native_memory(class为总的部分,包含了Metaspace area (excluding the Compressed Class Space)及Class Space)
    • Использование JMX для получения MemoryPoolMXBean с именем Metaspace и Compressed Class Space в типе NON_HEAP может привести к использованию Metaspace и Compressed Class Space (JMX得到的Metaspace为总的部分,而Metaspace area (excluding the Compressed Class Space)需要自己计算即total-class space)
    • Если это приложение Springboot, оно использует микрометр для предоставления связанных функций запроса индикатора через интерфейс /actuator/metrics, где Metaspace и Compressed Class Space находятся в метрике jvm.memory.used.

doc