記憶體洩漏排查
阿新 • • 發佈:2018-12-14
最近生產環境某專案突然崩潰,檢視堆疊發現虛擬堆已經滿了,檢視配置,
jmap -heap [pic]
堆記憶體為2G,理論上應該是夠用的,所以懷疑為記憶體洩漏,
使用
jmap -histo:live [pid]
列印堆中的物件,發現無法列印,
使用
jmap -dump:format=b,file=filename.hprof [pid]
匯出hprof 檔案,之後在HeapAnalyzer 上分析大物件,發現還是執行不了,強制打印出的檔案,放到軟體中解析不了,
最後緊急重啟了專案;
之後自己在測試環境模擬了下記憶體洩漏問題的排查,
使用btrace工具
下載地址
在伺服器上解壓
設定環境變數
BTRACE_HOME=/Users/wlxs/btrace-bin-1.3.8.3
export BTRACE_HOME
export PATH=$PATH:$BTRACE_HOME/bin
然後修改bin目錄下的btrace指令碼
JAVA_HOME=/usr/java/jdk1.6.0_43 BTRACE_HOME=/data/btrace_1.6 if [ -z "$BTRACE_HOME" -o ! -d "$BTRACE_HOME" ] ; then # resolve links - $0 could be a link to btrace's home PRG="$0" progname=`basename "$0"` BTRACE_HOME=`dirname "$PRG"`/.. BTRACE_HOME=`cd "$BTRACE_HOME" && pwd` fi if [ -f "${BTRACE_HOME}/build/btrace-client.jar" ] ; then if [ "${JAVA_HOME}" != "" ]; then case "`uname`" in Darwin*) # In Mac OS X, tools.jar is classes.jar and is kept in a # different location. Check if we can locate classes.jar # based on ${JAVA_VERSION} TOOLS_JAR="/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Classes/classes.jar" # if we can't find, try relative path from ${JAVA_HOME}. Usually, # /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home # is JAVA_HOME. (or whatever version beyond 1.6.0!) if [ ! -f ${TOOLS_JAR} ] ; then TOOLS_JAR="${JAVA_HOME}/../Classes/classes.jar" fi 以下省略 。。。
假設在堆疊中發現了大量的HashMap 遂編寫指令碼
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingHashMap { /*指明要檢視的方法,類*/ @OnMethod( clazz="java.util.HashMap", method="put", [email protected](Kind.RETURN)) public static void traceExecute(@Self java.util.HashMap object){ println("呼叫堆疊!!"); jstack(); } }
然後執行命令
./btrace [pid] TracingHashMap.java 即可檢視hashmap中put的執行細節