本文介绍CPU&内存诊断使用过程中的常见问题。

Profiler Tools的选择

因为一些基础设施导致无法做性能刨析的场景,需要提供Profiler Tools日志进行排查。Profiler Tools的日志所在路径为${ArmsAgentHome}/logs/cpc.log

OpenJDK

分析对象Profiler Tools(JDK 8 8u 272以下版本)Profiler Tools(JDK 8 8u 272及以上版本)Profiler Tools(JDK 11)Profiler Tools(JDK 17)
CPU ProfilerAsync-ProfilerJFRJFRJFR
Alloc ProfilerAsync-ProfilerAsync-ProfilerAsync-ProfilerJFR
  • JDK 8 u272以下版本:无JFR可用,需选择Async-Profiler。
  • JDK 8 u272到JDK 16版本:JFR实现的Alloc相关事件的开销较大,请选择Async-Profiler。
  • JDK 17及以上版本:如果支持使用JFR,推荐使用JFR。

Oracle JDK

分析对象Profiler Tools(JDK 8)Profiler Tools(JDK 11)Profiler Tools(JDK 17)
CPU ProfilerAsync-ProfilerJFRJFR
Alloc ProfilerAsync-ProfilerAsync-ProfilerJFR
  • Oracle JDK 8版本:JFR为商业特性,推荐使用Async-Profiler。
  • Oracle JDK 11及以上版本:JFR为开源特性,JFR实现的Alloc相关事件的开销较大,请选择Async-Profiler。
  • 其他版本:如果支持使用JFR,推荐使用JFR。

Async-Profiler问题

如何解决perf_event_open被限制问题?

问题现象

Async-Profiler进行CPU Profiler依赖perf_event_open的系统调用,但因为Linux kernel的Syscall安全策略(seccomp)控制,可能会禁止进程调用特定Syscall。

错误提示如下:
[ERROR] Failed to execute 'start,jfr=0,event=cpu,interval=11ms,alloc=512k,file=/tmp/cpc-async-profiler-7729534006755968198.jfr'
[ERROR] Failed to start Continuous Profile Collector
java.lang.RuntimeException: java.lang.IllegalStateException: No access to perf events. Try --fdtransfer or --all-user option or 'sysctl kernel.perf_event_paranoid=1'

解决方案

  • Docker环境:执行以下命令运行容器。如需配置更精细化的系统调用控制,请参见官方文档
      docker run --security-opt seccomp=unconfined  XXX
  • Kubernetes环境:配置特权容器参数privileged: true,特权容器始终保持为Unconfined

    如需配置更精细化的系统调用控制,请参见官方文档

如何解决No AllocTracer symbols found问题?

问题现象

Async-Profiler进行内存剖析需要依赖JDK的符号信息,如果JDK内无符号信息,则会遇到如下问题:
[ERROR] Failed to start Continuous Profile Collector
java.lang.RuntimeException: java.lang.IllegalStateException: No AllocTracer symbols found. Are JDK debug symbols installed?

解决方案

  1. 执行以下命令,确认是否已经配置了debuginfo的源。
    yum repolist all | grep -i debug

    通过返回信息确认源配置信息是否如下:

    debuginfo/7/x86_64 CentOS-7 - debuginfo - mirrors.aliyun.com 启用: 8,760

    如果未配置debuginfo的源,则执行步骤2增加配置;如果已经配置,则执行步骤3

  2. 在yum配置文件中增加debuginfo的配置。
    vi /etc/yum.repos.d/CentOS-Base.repo
    [debuginfo]
    name=CentOS-$releasever - debuginfo - mirrors.aliyun.com
    failovermethod=priority
    baseurl=http://mirrors.aliyun.com/centos-debuginfo/$releasever/$basearch/
    gpgcheck=1
    enabled=1
    gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Debug-7
    保存后执行如下命令:
    yum clean all
    yum makecache
    yum-config-manager --enable debuginfo
  3. 安装JDK版本对应的符号信息。

    JDK 8

    yum list installed|grep openjdk    //查询JDK版本。
    java-1.8.0-openjdk.x86_64          1:1.8.0.332.b09-1.el7_9            @updates
    
    debuginfo-install -y java-1.8.0-openjdk      //安装符号信息。

    JDK 11

    yum list installed|grep openjdk    //查询JDK版本。
    java-11-openjdk.x86_64             1:11.0.15.0.9-2.el7_9              @updates
    
    debuginfo-install -y java-11-openjdk      //安装符号信息。
  4. 检查JDK的符号信息是否已经安装成功。
    gdb $JAVA_HOME/lib/server/libjvm.so -ex 'info address UseG1GC'
    gdb /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server/libjvm.so -ex 'info address UseG1GC'
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
    Copyright (C) 2013 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server/libjvm.so...Reading symbols from /usr/lib/debug/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server/libjvm.so.debug...done.
    done.
    如果安装正确,返回信息如下:
    Symbol "UseG1GC" is static storage at address 0x107f993.
    如果安装失败,返回信息如下:
    No symbol "UseG1GC" in current context.
  5. 如果Java进程运行在容器环境,则需要修改容器的Dockerfile,确保容器镜像内包含JDK的符号信息。

其他问题

您可以通过查阅Async-Profiler解决运行时的依赖问题,如果还有其他问题请联系我们(钉钉用户群号:22560019672)。