编译后的代码存储在 JVM CodeCache 区域中



一台服务器的CPU使用率逐渐下降到100%,我发现CodeCache区域占用了231M,而阈值是240M。

我的集群中的其他服务器很好,CPU使用率为30%,CodeCache区域占用了110M。

我想知道在服务器无法重新启动时,CodeCache 区域中存储了哪些编译代码以避免破坏场景。

它是否存在代码缓存转储?

PS:JDK版本是1.8

对于更新的 JDK 版本,您可以使用 jcmd Compiler.codecache jcmd Comiler.codelist 。对于 1.8,请尝试 -XX:+PrintCodeCache 或 –XX:+PrintCodeCacheOnCompilation,尽管这只会为您提供摘要统计信息(请参阅有没有办法监视 Java 中编译的代码缓存?(。

jcmd codelist 命令由 JVM 的 CodeCache::print_codelist 方法处理,但这在 JDK 8 中不可用 - 所有内容都是print_summary

PS:我也尝试使用gcore生成核心转储,但未能看到如何以这种方式分析代码缓存。

这是一个简单的程序,可用于在JDK 8上转储CodeCache。

import sun.jvm.hotspot.code.CodeBlob;
import sun.jvm.hotspot.code.CodeCacheVisitor;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;
public class DumpCodeCache extends Tool {
    @Override
    public void run() {
        VM.getVM().getCodeCache().iterate(new CodeCacheVisitor() {
            public void prologue(Address start, Address end) {
            }
            public void visit(CodeBlob blob) {
                System.out.printf("%8d  %sn", blob.getSize(), blob.getName());
            }
            public void epilogue() {
            }
        });
    }
    public static void main(String[] args) {
        new DumpCodeCache().execute(args);
    }
}

该工具基于Serviceabiliy Agent技术。
若要编译并运行它,请在类路径中包含$JAVA_HOME/lib/sa-jdi.jar

java -cp $JAVA_HOME/lib/sa-jdi.jar:. DumpCodeCache PID

从 JDK 9 开始,有一个内置功能可以使用 jcmd 转储 CodeCache:

jcmd PID Compiler.codelist

从 JDK 11 开始,还有更强大的命令来打印详细的 CodeCache 统计信息:

jcmd PID Compiler.CodeHeap_Analytics