最近生产环境某项目突然崩溃,查看堆栈发现虚拟堆已经满了,查看配置,
jmap -heap [pic]
堆内存为2G,理论上应该是够用的,所以怀疑为内存泄漏,
使用
jmap -histo:live [pid]
打印堆中的对象,发现无法打印,
使用
jmap -dump:format=b,file=filename.hprof [pid]
导出hprof 文件,之后在HeapAnalyzer 上分析大对象,发现还是执行不了,强制打印出的文件,放到软件中解析不了,
最后紧急重启了项目;
之后自己在测试环境模拟了下内存泄漏问题的排查,
使用btrace工具
下载地址
https://github.com/btraceio/btrace/releases/tag/v1.3.8.3-1
在服务器上解压
设置环境变量
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",
location=@Location(Kind.RETURN))
public static void traceExecute(@Self java.util.HashMap object){
println("调用堆栈!!");
jstack();
}
}
然后执行命令
./btrace [pid] TracingHashMap.java 即可查看hashmap中put的执行细节
参考: https://www.jianshu.com/p/1b52561e3848
https://blog.csdn.net/aasgis6u/article/details/54928744