本文介紹持續剖析使用過程中的常見問題。
parse lib sigsegv handler installed日誌列印
問題原因
該日誌是ARMS探針列印的無用日誌,僅在開啟持續剖析功能後才會列印,對應用運行過程無影響,另外ARMS會在將來的新版本中關閉相關日誌列印。
perf_event_open被限制導致的No access to perf events報錯問題
問題現象
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'
解決方案
No AllocTracer symbols found .Are JDK debug symbols installed?報錯問題
問題現象
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?
解決方案
如果Java進程運行在容器環境,出現以上報錯或者該功能無資料,一般都是由於使用了Alpine基礎鏡像導致,Alpine基礎鏡像為了控制體積而去除了JDK偵錯符號(debug symbols),影響持續剖析能力正常使用,建議在基礎鏡像中為JDK安裝調試符(部分JDK版本缺乏對應的調試符包,會導致無法安裝)或使用非Alpine基礎鏡像。
如果是CentOS物理機環境部署應用可通過以下步驟安裝調試符:
執行以下命令,確認是否已經配置了debuginfo的源。
yum repolist all | grep -i debug
通過返回資訊確認源配置資訊是否如下:
debuginfo/7/x86_64 CentOS-7 - debuginfo - mirrors.aliyun.com 啟用: 8,760
在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
安裝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 #安裝符號資訊。
檢查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.
perf_event mmap failed...報錯問題
問題現象
此錯誤一般出現在JVM的標準輸出中。持續剖析功能進行CPU熱點採樣時,會同時採集Native(Linux Kernel + JVM + C/C++)以及Java棧,採集Native棧需要對Java中每個線程的perf_event的fd進行MMap,Linux核心中限制了進程perf_event相關的MMap的總記憶體大小(預設516 K Bytes)。當Java中線程數較多時,會觸發限制並在Java標準輸出中列印警告資訊perf_event mmap failed...
。出現這個警示資訊,對Java的運行沒有副作用,對業務也沒有影響,實際的影響是火焰圖中看不到Native的棧。一般來說定位CPU熱點問題時,只看Java方法棧就夠了,您可以忽略此警示。
解決方案
如果想消除這個錯誤資訊,可以執行以下步驟:
在宿主機上執行以下命令。
echo 1028 > /proc/sys/kernel/perf_event_mlock_kb
預設閾值是516,可以逐漸增加,直到不出現警示,該值最好滿足
8*N + 4
,N是自然數。例如516 = 512 + 4, 1028 = 1024 + 4。重啟Docker,即可消除錯誤。
火焰圖中為什麼出現other項?
問題現象
如下圖所示火焰圖中出現other項。
問題原因
火焰圖中出現other項是正常的。火焰圖是一棵樹,當節點數較多時不便於從圖中提取關鍵資訊,因此ARMS通過一些方法對火焰圖中的節點進行收斂,將一些重要性相對較低的節點併入到other項中。
火焰圖中為什麼出現.no_Java_frame項?
一般是由於使用了Alpine基礎鏡像,Alpine基礎鏡像為了控制體積而去除了JDK偵錯符號(debug symbols),導致JDK裡面的C++線程中的方法棧無法識別出函數名字,只能顯示為no_Java_frame,由於這些方法棧主要是非Java的線程執行資訊,一般常見如VM Thread或者JIT編譯器線程,如果no_Java_frame相關內容佔比不高,可以忽略,重點觀察其他Java方法棧資訊做效能分析,如果no_Java_frame相關內容佔比較高,建議在基礎鏡像中為JDK安裝調試符(部分JDK版本缺乏對應的調試符包,會導致無法安裝)或使用非Alpine基礎鏡像。