1. 程式人生 > >記憶體洩漏排查

記憶體洩漏排查

最近生產環境某專案突然崩潰,檢視堆疊發現虛擬堆已經滿了,檢視配置,

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的執行細節