前置操作先定位pid、tid:
1. 一般是运维团队首先受到报警信息(CPU Memory)
2. top命令观察到问题:内存不断增长 CPU占用率居高不下
3. top -Hp 观察进程中的线程,哪个线程CPU和内存占比高
1.jstack:导出java进程中各个栈内线程信息 eg:jstack -l 12306 >>threadlog.txt 将进程号为12306相关的线程信息导入到threadlog.txt文件中 内容如下:
2.jinfo pid 查看当前虚拟机的运行参数
3.jconsole/jvisualVM 图形化界面监测jvm进程中线程、cpu、内存、变量 如果连接远程机需要远程机上的项目启动时设置相关参数,本地线程无需设置,如何实现不配置远程主机的启动参数实现监测:https://blog.csdn.net/keketrtr/article/details/53516011
jvisualVM 能看到的细节更多,如果要有图形化界面检测推荐使用jvisualVM,在很多的压力测试时使用
目启动时设置相关参数举例:
nohup java \
-Djava.rmi.server.hostname=192.250.110.153 -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=1099 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \
-jar sp-provider-1.0.0-SNAPSHOT.jar >/dev/null
4.jmap 是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生了哪些对象,及其数量,对象内部存值等)。 jmap可以主动导出jvm内存信息,也可以在项目启动时指定在程序内存溢出时自动导出内存信息
使用参考https://www.jianshu.com/p/a4ad53179df3
最常用命令:
jmap -histo:live
pid 查看进程中对象存活状况 包括数量,占用内存,类型等
jmap -dump:format=b,file=heapdump.phrof pid 导出堆转储快照dump文件,生产环境谨慎使用(线上系统,内存特别大,jmap -dump执行期间会对进程产生很大影响,甚至卡顿【电商系统不适合乱用】,jvisualVM监控时也能操作导出dump,以同样会卡顿),用相关的分析工具将文件进行分析。
项目内存溢出时导出堆快照:java -jar -Xms2000M -Xmx2000M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof xxx.jar ; HeapDumpOnOutOfMemoryError:内存溢出导出堆文件,HeapDumpPath:指定堆文件输出路径
5.Memory Analyzer(MAT)分析堆内存DUMP 文件,
使用参考:https://www.javatang.com/archives/2017/10/30/53562102.html
https://www.javatang.com/archives/2017/11/08/11582145.html
或者jvisualVM进行DUMP 文件文件的简要分析;
6.或者使用jhat是sun 1.6及以上版本中自带的一个用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中对象的内存占用情况
jhat -J-Xmx1024M [file]
eg: jhat -J-Xmx1024M heapdump.phrof
执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000 输出的内用比较繁琐复杂
一次项目并发压测,出现OOM,通过jstack没有发现异常进程,之后jmap导出dump堆转储文件,使用jvisualVM进行分析时发现有一类httprequest的请求对象占用内存极高,数量正常但是单个占用较大,初步判断是因为这个变量造成的oom,之后通过本地调试发现,内部指定的一个head相关的一个属性的开辟的字节空间极大,建立了一个属性监控断定,最终定位属性的空间开辟是由一个spring中的一个变量