1. Introduction
1.介绍
In this tutorial, we’re going to have a quick look at and learn about the JVM’s code cache memory.
在本教程中,我们将对JVM的代码缓存内存进行快速浏览和学习。
2. What Is the Code Cache?
2.什么是代码缓存?
Simply put, JVM Code Cache is an area where JVM stores its bytecode compiled into native code. We call each block of the executable native code a nmethod. The nmethod might be a complete or inlined Java method.
简单地说,JVM Code Cache是JVM存储其编译成本地代码的字节码的一个区域。我们把可执行的本地代码的每个块称为nmethod。这个nmethod可能是一个完整的或内联的Java方法。
The just-in-time (JIT) compiler is the biggest consumer of the code cache area. That’s why some developers call this memory a JIT code cache.
及时编译器(JIT)是代码缓存区的最大消费者。这就是为什么有些开发者把这块内存称为JIT代码缓存。
3. Code Cache Tuning
3.代码缓存的调整
The code cache has a fixed size. Once it is full, the JVM won’t compile any additional code as the JIT compiler is now off. Furthermore, we will receive the “CodeCache is full… The compiler has been disabled” warning message. As a result, we’ll end up with degraded performance in our application. To avoid this, we can tune the code cache with the following size options:
代码缓存有一个固定的大小。一旦它满了,JVM就不会再编译任何额外的代码,因为JIT编译器现在是关闭的。此外,我们将收到“CodeCache已满…编译器已被禁用“的警告信息。结果是,我们的应用程序的性能会下降。为了避免这种情况,我们可以通过以下的大小选项来调整代码缓存。
- InitialCodeCacheSize – the initial code cache size, 160K default
- ReservedCodeCacheSize – the default maximum size is 48MB
- CodeCacheExpansionSize – the expansion size of the code cache, 32KB or 64KB
Increasing the ReservedCodeCacheSize can be a solution, but this is typically only a temporary workaround.
增加ReservedCodeCacheSize可以是一个解决方案,但这通常只是一个临时的解决方法。
Fortunately, the JVM offers a UseCodeCacheFlushing option to control the flushing of the code cache area. Its default value is false. When we enable it, it frees the occupied area when the following conditions are met:
幸运的是,JVM提供了一个UseCodeCacheFlushing选项来控制代码缓存区的冲洗。它的默认值是false。当我们启用它时,当满足以下条件时,它会释放被占用的区域:。
- the code cache is full; this area is flushed if its size exceeds a certain threshold
- the certain interval is passed since the last cleanup
- the precompiled code isn’t hot enough. For each compiled method the JVM keeps track of a special hotness counter. If the value of this counter is less than a computed threshold, the JVM frees this piece of precompiled code
4. Code Cache Usage
4.代码缓存的使用
In order to monitor the code cache usage, we need to track the size of the memory currently in use.
为了监控代码缓存的使用情况,我们需要跟踪当前正在使用的内存的大小。
To get information on code cache usage, we can specify the –XX:+PrintCodeCache JVM option. After running our application, we’ll see a similar output:
为了获得代码缓存的使用信息,我们可以指定-XX:+PrintCodeCache JVM选项。在运行我们的应用程序后,我们会看到一个类似的输出。
CodeCache: size=32768Kb used=542Kb max_used=542Kb free=32226Kb
Let’s see what each of these values mean:
让我们看看这些数值分别意味着什么。
- size in the output shows the maximum size of the memory, which is identical to ReservedCodeCacheSize
- used is the actual size of the memory that currently is in use
- max_used is the maximum size that has been in use
- free is the remaining memory which is not occupied yet
The PrintCodeCache option is very useful, as we can:
PrintCodeCache选项非常有用,因为我们可以。
- see when the flushing happens
- determine if we reached a critical memory usage point
5. Segmented Code Cache
5.分段式代码缓存
As of Java 9, the JVM divides the code cache into three distinct segments each of which contains a particular type of compiled code. To be more specific, there are three segments:
从Java 9开始,JVM将代码缓存划分为三个不同的段,每个段都包含一种特定类型的编译代码。更具体地说,有三个段。
- The non-method segment contains JVM internal related code such as the bytecode interpreter. By default, this segment is around 5 MB. Also, it’s possible to configure the segment size via the -XX:NonNMethodCodeHeapSize tuning flag
- The profiled-code segment contains lightly optimized code with potentially short lifetimes. Even though the segment size is around 122 MB by default, we can change it via the -XX:ProfiledCodeHeapSize tuning flag
- The non-profiled segment contains fully optimized code with potentially long lifetimes. Similarly, it’s around 122 MB by default. This value is, of course, configurable via the -XX:NonProfiledCodeHeapSize tuning flag
This new structure treats various types of complied code differently, which leads to better overall performance.
这种新的结构对各种类型的编译代码进行了不同的处理,这导致了更好的整体性能。
For example, separating short-lived compiled code from long-lived code improves the method sweeper performance — mainly because it needs to scan a smaller region of memory.
例如,将短命的编译代码与长命的代码分开,可以提高方法清扫器的性能–主要是因为它需要扫描的内存区域更小。
6. Conclusion
6.结论
This quick article presents a brief introduction to the JVM Code Cache.
这篇快速文章简要介绍了JVM代码缓存。
Additionally, we presented some usage and tune-up options to monitor and diagnose this memory area.
此外,我们提出了一些使用和调整选项,以监测和诊断这一内存区域。