Talk about jvm Code Cache

  jvm

Order

This article mainly studies the Code Cache of jvm.

Code Cache

The memory space of native code generated by JVM is called codecache. JIT compilation and JNI compile code to native code, where the native code generated by JIT takes up most of the space in Code Cache.

Related parameters

Codecache Size Options

  • -XX:InitialCodeCacheSize

Used to set the initial CodeCache size

  • -XX:ReservedCodeCacheSize

Used to set the maximum size of Reserved code cache, which is usually 240M by default

  • -XX:CodeCacheExpansionSize

The expansion size used to set code cache is usually 64K by default.

Codecache Flush Options

  • -XX:+UseCodeCacheFlushing

Do you want to try to clean up the code cache when it is full? if it is still not enough, then close compilation and it will be turned on by default

Compilation Policy Options

  • -XX:CompileThreshold

The number of calls when the method triggers compilation; the default is 10000

  • -XX:OnStackReplacePercentage

In the method, the number of times the code is executed circularly triggers the OSR compile-time threshold, which defaults to 140

Compilation Limit Options

  • -XX:MaxInlineLevel

The maximum inline depth for nested calls is 9 by default

  • -XX:MaxInlineSize

The maximum bytecode size the method can be inlined, which defaults to 35

  • -XX:MinInliningThreshold

The minimum number of times a method can be called inline is 250 by default

  • -XX:+InlineSynchronizedMethods

Whether to allow inline synchronized methods, the default is true

Diagnostic Options

  • -XX:+PrintFlagsFinal(Not enabled by default)

Used to view all settable parameters and final values (JDK 6 update 21 is not available until it is started.), the default is not including diagnostic or Empirical. If you want to see the information of these two parameters in the output of–XX:+PrintFlagsFinal, you need to explicitly specify-xx:+unlockdiagnosticvmoptions/-xx:+unlockxperimentalvmoptions (-XX:+PrintCommandLineFlags this parameter is used to display all parameters different from the original default value and their values after VM initialization)

  • -XX:+PrintCodeCache(Not enabled by default)

-XX:+PrintCodeCache is used to output code cache usage when jvm is shut down

  • -XX:+PrintCodeCacheOnCompilation(Not enabled by default)

Used to output the usage of code cache each time the method is compiled.

View Code Cache usage

-XX:+PrintCodeCache

CodeHeap 'non-profiled nmethods': size=120032Kb used=2154Kb max_used=2160Kb free=117877Kb
 bounds [0x00000001178ea000, 0x0000000117b5a000, 0x000000011ee22000]
CodeHeap 'profiled nmethods': size=120028Kb used=10849Kb max_used=11005Kb free=109178Kb
 bounds [0x00000001103b3000, 0x0000000110e73000, 0x00000001178ea000]
CodeHeap 'non-nmethods': size=5700Kb used=1177Kb max_used=1239Kb free=4522Kb
 bounds [0x000000010fe22000, 0x0000000110092000, 0x00000001103b3000]
 total_blobs=5638 nmethods=4183 adapters=435
 compilation: enabled
              stopped_count=0, restarted_count=0
 full_count=0
  • The jvm startup parameter plus -XX:+PrintCodeCache can output the usage of code cache when the jvm is shut down.
  • Here, it is divided into three parts: non-profiled nmethods, profit NMethods and non-profit NMethods to show them.
  • Where size is the maximum limit, used is the actual usage, max_used is the high water mark of the usage size, and free is obtained from size-used

jcmd pid Compiler.codecache

/ # jcmd 1 Compiler.codecache
1:
CodeHeap 'non-profiled nmethods': size=120036Kb used=1582Kb max_used=1582Kb free=118453Kb
 bounds [0x00007f1e42226000, 0x00007f1e42496000, 0x00007f1e4975f000]
CodeHeap 'profiled nmethods': size=120032Kb used=9621Kb max_used=9621Kb free=110410Kb
 bounds [0x00007f1e3acee000, 0x00007f1e3b65e000, 0x00007f1e42226000]
CodeHeap 'non-nmethods': size=5692Kb used=1150Kb max_used=1198Kb free=4541Kb
 bounds [0x00007f1e3a75f000, 0x00007f1e3a9cf000, 0x00007f1e3acee000]
 total_blobs=5610 nmethods=4369 adapters=412
 compilation: enabled
              stopped_count=0, restarted_count=0
 full_count=0

Compiler.code cache using jcmd can also view the usage of codecache. the output is the same as -XX:+PrintCodeCache

jcmd pid VM.native_memory

/ # jcmd 1 VM.native_memory
1:

Native Memory Tracking:

Total: reserved=1928023KB, committed=231182KB
-                 Java Heap (reserved=511488KB, committed=140288KB)
                            (mmap: reserved=511488KB, committed=140288KB)

-                     Class (reserved=1090832KB, committed=46608KB)
                            (classes #8218)
                            (  instance classes #7678, array classes #540)
                            (malloc=1296KB #19778)
                            (mmap: reserved=1089536KB, committed=45312KB)
                            (  Metadata:   )
                            (    reserved=40960KB, committed=39680KB)
                            (    used=38821KB)
                            (    free=859KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=5632KB)
                            (    used=5190KB)
                            (    free=442KB)
                            (    waste=0KB =0.00%)

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

-                      Code (reserved=248651KB, committed=15351KB)
                            (malloc=963KB #4600)
                            (mmap: reserved=247688KB, committed=14388KB)

-                        GC (reserved=21403KB, committed=7611KB)
                            (malloc=5419KB #9458)
                            (mmap: reserved=15984KB, committed=2192KB)

-                  Compiler (reserved=150KB, committed=150KB)
                            (malloc=20KB #447)
                            (arena=131KB #5)

-                  Internal (reserved=3744KB, committed=3744KB)
                            (malloc=1696KB #6416)
                            (mmap: reserved=2048KB, committed=2048KB)

-                     Other (reserved=24KB, committed=24KB)
                            (malloc=24KB #2)

-                    Symbol (reserved=10094KB, committed=10094KB)
                            (malloc=7305KB #219914)
                            (arena=2789KB #1)

-    Native Memory Tracking (reserved=4130KB, committed=4130KB)
                            (malloc=12KB #158)
                            (tracking overhead=4119KB)

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

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

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

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

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

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

VM.native_memory using jcmd can also view code cache usage (Code section), the Compiler part is memorytracking used by the compiler when generating code.

Use MemoryPoolMXBean to view

    @Test
    public void testGetCodeCacheUsage(){
        ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)
                .stream()
                .filter(e -> MemoryType.NON_HEAP == e.getType())
                .filter(e -> e.getName().startsWith("CodeHeap"))
                .forEach(e -> {
                    LOGGER.info("name:{},info:{}",e.getName(),e.getUsage());
                });
    }

MemoryPoolMXBean contains HEAP and NON_HEAP, where code cache belongs to NON_HEAP, and its output is as follows:

12:21:10.728 [main] INFO com.example.CodeCacheTest - name:CodeHeap 'non-nmethods',info:init = 2555904(2496K) used = 1117696(1091K) committed = 2555904(2496K) max = 5836800(5700K)
12:21:10.743 [main] INFO com.example.CodeCacheTest - name:CodeHeap 'profiled nmethods',info:init = 2555904(2496K) used = 1543808(1507K) committed = 2555904(2496K) max = 122908672(120028K)
12:21:10.743 [main] INFO com.example.CodeCacheTest - name:CodeHeap 'non-profiled nmethods',info:init = 2555904(2496K) used = 319616(312K) committed = 2555904(2496K) max = 122912768(120032K)

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: Sat, 30 Mar 2019 04:26:39 GMT

{"name":"jvm.memory.used","description":"The amount of used memory","baseUnit":"bytes","measurements":[{"statistic":"VALUE","value":6.5295408E7}],"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:CodeHeap%20%27non-profiled
%20nmethods%27"
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: Sat, 30 Mar 2019 04:24:58 GMT

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

Springboot uses micrometer to provide relevant index query function through/actor/metric interface, in which code cache is 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

  • The memory space of native code generated by JVM is called codecache. JIT compilation and JNI compile code to native code, where the native code generated by JIT takes up most of the space in Code Cache.
  • –XX:Reserved code cacheSize used to set the maximum size of Reserved CodeCache, which is usually 240 m by default; For code applications, 240M may be too large, and code cache may not be full, which is equivalent to unconstrained. at this time, JIT will continue compiling any codethat it thinks can be compiled.
  • There are several ways to view the memory usage of Code Cache:

    • The jvm startup parameter plus -XX:+PrintCodeCache can output the usage of code cache when the jvm is shut down.
    • Compiler.codecache using jcmd, its output is the same as -XX:+PrintCodeCache;
    • VM.native_memory using jcmd can also view code cache usage (Code section)
    • Using JMX to get MemoryPoolMXBean whose name starts with CodeHeap in NON_HEAP type can get the usage of code cache.
    • If it is a springboot application, it uses micrometer to provide relevant index query function through/actor/metric interface, where code cache is in jvm.memory.used

doc