JVM 代码缓存超过 ReservedCodeCacheSize

问题描述

我有一个在 docker 中运行的 Java 应用程序,带有 OpenJDK8 上的标志:

-XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0 -XX:NativeMemoryTracking=summary

并且我注意到本机内存跟踪工具报告的代码缓存内存分配超过 240MBReservedCodeCacheSize 值):

jcmd 1 VM.native_memory summary | grep -i code
-                      Code (reserved=260013KB,committed=60465KB)

这是 ~ 254MB 保留的内存。这是打印的标志和 java 版本:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep -i reserved
    uintx ReservedCodeCacheSize                     = 251658240                           {pd product}
openjdk version "1.8.0_262"
OpenJDK Runtime Environment (build 1.8.0_262-b10)
OpenJDK 64-Bit Server VM (build 25.262-b10,mixed mode)

我的问题是这是否是预期行为?如果是,那么是否可以计算最大代码缓存大小的实际限制?

谢谢!

解决方法

本机内存跟踪报告中的

Code 不仅说明了代码缓存,还说明了其他一些内容。报告包括:

  1. 使用 mmap 保留的固定大小空间:
    • 代码缓存 - 240 MB;
    • 代码缓存段的映射 - 代码缓存大小的 1/64 = 3.75 MB。
  2. 在本机堆中 malloc 的辅助 VM 结构:
    • 代码字符串、OopMaps、异常处理程序缓存、适配器处理程序表和其他用于维护生成代码的结构。

      这些结构是动态分配的;对它们没有专门的限制,但通常它们只占总生成代码的一小部分(请参阅 NMT 报告 malloc= 部分中的 Code 行)。

请注意,reserved 内存实际上并不消耗地址空间以外的资源。对于分析实际内存使用情况,committed 更相关。