什么已编译的代码存储在JVM CodeCache区域中

时间:2019-07-12 03:05:15

标签: java jvm jit

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

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

我想知道什么已编译的代码存储在CodeCache区域中,而服务器无法重新启动以避免破坏现场。

是否存在代码缓存转储?

ps:jdk版本为1.8

2 个答案:

答案 0 :(得分:1)

使用最新的JDK版本,您可以使用jcmd Compiler.codecache jcmd Comiler.codelist 。 对于1.8,请尝试-XX:+ PrintCodeCache或–XX:+ PrintCodeCacheOnCompilation,尽管这只会给您提供摘要统计信息(请参阅Is there any way to monitor the compiled code cache in Java?)。

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

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

答案 1 :(得分:1)

这是一个简单的程序,可用于在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  %s\n", 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