JAR包的启动命令加-XX:+HeapDumpOnOutOfMemoryError
在jar包的启动命令增加参数-XX:+HeapDumpOnOutOfMemoryError,该命令会打印出内存泄漏的信息;
nub=8888
perpid=`netstat -tunlp|grep $nub |awk '{print $7}'`
if [ $perpid ];then
#从后开始删除变量,删除到第一个/停止,赋值给apid
apid=${perpid%/*}
echo "获取 $nub 端口进程号:$apid"
#杀死进程
kill -9 $apid
echo "杀死占用 $nub 端口进程(pid:$apid)"
else
echo "没有进程占用 $nub 端口"
fi
nohup java -javaagent:/export/server/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jar=agent.service_name=community,collector.backend_service=192.168.88.152:11800 -jar -Djava.rmi.server.hostname=192.168.88.151 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8889 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dfile.encoding=UTF-8 -Dspring.profiles.active=dev -Xms250m -Xmx250m -XX:+HeapDumpOnOutOfMemoryError community-0.0.1-SNAPSHOT.jar &
执行压测脚本
压测结果监控分析
压测几分钟后,出现系统宕机(接口响应时间大量超时,接口出现大量的报错,TBS直接躺平接近为0 )
TPS和响应时间一开始会表现的非常不稳定,中间出现大量的断层,断层原因是进行了大量的FULL GC,FULL GC需要消耗大量的资源(可以看下面JVM的监控的图片),压多几分钟后,系统直接宕机;
JVM的堆进行频繁的FULL GC,内存表现为上升的趋势,到后面系统直接挂掉;
定位内存泄漏
-XX:HeapDumpPath
当程序出现OOM
的时候,会服务在jar包的当前目录下生成一个java_pid$pid.hprof
二进制文件。
这个java_pid$pid.hprof
也可通过jmap
命令来即时生成:jmap -dump:format=b,file=java_pid$pid.hprof $pid
($ pid为java进程ID)
下面就是使用工具分析这个.hprof
文件来定位问题了。使用Jvisual来分析该文件,效果如下:
Jvisual在jdk的bin目录下,点击打开
点击文件>装入
然后选择从服务器下载下来的dump文件(文件类型选择dump,不然找不到)
我们可以看到,接口确定出现了内存泄漏,点击异常的线程,查看具体是JAVA代码的哪个类里面的代码发送了内存泄漏;
我们可以看到是出现了内存存储泄漏,点击进去可以看下代码的具体类的哪行代码发生了内存泄漏,我写的接口是,我创建了一个ArraryList,接口调用一次,往里面写5M的数据,然后不回收;
后续讲解下,目前主流的线上定位工具arthas定位内存泄漏的问题