目录
JDK命令行
Eclipse Memory Analyzer
JMX - Jconsole, VisualVM
Btrace
Flight Recorder Java Mission Control
JProfiler
火焰图
线上服务有时候我们会碰到下面这些问题:
OutOfMemoryError,内存不足
内存泄露
线程死锁
锁争用(Lock Contention)
Java进程消耗CPU过高
jps
主要用来输出JVM中运行的进程状态信息。语法格式如下:
jps [options] [hostid]
命令行参数选项说明如下:
-q 不输出类名、Jar名和传入main方法的参数
-m 输出传入main方法的参数
-l 输出main类或Jar的全限名
-v 输出传入JVM的参数
jstack
主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:
jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
命令行参数选项说明如下:
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
实例:找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。
1、找出java进程Id, 通过匹配部署在服务器上的java应用名称
ps -ef | grep mibi-admin-timertask
得到进程ID为29051
2、找出该进程内最耗费CPU的线程, TIME列就是各个Java线程耗费的CPU时间
top -Hp 29051
这里得到的pid为:29168
3、得到该pid的十六进制值
printf "%x\n" 29168
该十六进制值为71f0
4、输出进程29051的堆栈信息(是进程pid,不是线程pid)
jstack 29051 | grep 71f0
可以看到CPU消耗在某个类的方法上,然后匹配相应代码即可。
jstat (JVM统计监测工具)
语法格式如下:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid是Java虚拟机ID,在Linux/Unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。
例如:
jstat -gcutil 62147 1000
jmap 内存使用情况,导出内存镜像文件
查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况
jmap -heap pid
用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:
jmap -dump:format=b,file=dumpFileName pid
(线上服务不推荐该工具,因为当dump下来内存数据文件时,可能因为文件过大直接压垮系统,影响线上的服务)
官网:
https://www.eclipse.org/mat/
在Eclipse中安装说明
打开Eclipse->Help->Eclipse Marketplace,搜索memory,如下:
打开eclipse后,点击eclipse的file---->open file 找到指定生成的hprof文件位置打开,生成下图报表,选择默认选项 Leak Suspects Report,打开之后的主界面如下图:
第一个菜单:Overview,显示了概要信息,并且展示了MAT常用功能,如下图:
第二个菜单:Histogram,显示了每个类实例的数量和大小,大小包括ShallowHeap,和RetainedHeap,如下图:
第三个菜单:Dominator_tree,列出HeapDump中处于活跃状态的最大的对象,默认按着RetainedHeap排序,很容易找到占用内存最多的对象,如下图:
第四个菜单:OQL,面向对象查询语言(OQL),类似SQL,将类当做表,一个对象当做一条记录行,成员变量当做表中的字段。点击红色叹号(Execute Query),进行查询,如下图:
第五个菜单:ThreadOverride,查看生成HeapDump文件的时候,线程的运行情况,可以用于线程分析,如下图:
采用下面的“三步曲”来分析内存泄露问题:
第一步,对问题发生时刻的系统内存状态获取一个整体印象。
第二步,找到最有可能导致内存泄露的元凶,通常也就是消耗内存最多的对象。
最后,去查看这个内存消耗大户的具体情况,看看是否有什么异常的行为。
Jconsole官网:https://docs.oracle.com/javase/tutorial/jmx/
VisualVM官网:https://visualvm.github.io/
Jconsole
在java的bin目录下即可打开,连接你想连接的Java应用程序。
通过Jconsole工具,可以查看Java应用程序的运行概况,可以监控堆信息、永久区使用情况、类加载情况。
如果需要使用JConsole连接远程进程,需要在启动服务器上的java应用时添加参数:
-Dcom.sun.management.jmxremote.host=127.0.0.1
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
进行远程连接时,只需要填写如下远程进程即可:
127.0.0.1:8888
内存监控页面点击"执行GC"按钮,可以强制应用程序执行一次Full Gc。
线程监控页面点击"检测到死锁"按钮,可以自动检测多线程应用程序的死锁情况。
VisualVM
可以替代jstat、jmap、jhat、jstack,甚至可以代替Jconsole。在java的bin目录打开后,可以进行本地连接,也可以进行远程连接,远程连接的配置跟上面的Jconsole远程连接时一样。
从java1.7开始,visual vm 就作为JDK的一部分了,打开bin目录下的jvisualvm.exe。
Thread Dump和分析
线程页面提供详细的线程信息,单击“线程Dump”按钮可以导出当前所有线程的堆栈信息,相当于jstack命令。
如果Visual Vm在当前程序中找到死锁,会在页面中给予提示。
性能分析
抽样页面中CPU按钮可以查看CPU占用时间定位到方法,内存按钮可以查看当前程序的堆信息。
CPU采样器可以定位到系统中最消耗资源的方法。另外,如果想统计JDK内置对象的函数调用统计,请勾选设置进行配置。
内存采样器可以实时查看系统中实例的分布情况。
内存快照分析
下图为获取当前应用程序的内存快照,相当于jmap命令。
内存快照分析如下图,基本功能页:概要、类、实例数和OQL控制台。
类页面可以对两个不同的内存快照文件进行比较,帮助我们快速分析同一应用程序在运行的不同时刻,内存数据产生的变化。
可以做更精细化的追踪控制。在不停机的情况下,通过字节码注入动态监控系统的运行情况,可以跟踪指定的方法调用、构造函数调用和系统内存等信息。
在Visual VM中安装Btrace插件,点击工具,然后查看可用插件,就能进行安装了。
点击“Trace application"进入BTrace插件页面,在代码区完成Btrace脚本的编写,单击start按钮将BTrace脚本注入选中应用程序。
@OnMethod注释指定要监控的类和方法名称。
@ProbeClassName 类名
@ProbeMethodName 方法名
AnyType[] 传递给方法的参数
下面的脚本是监控每次涉及匹配到的方法的调用时,输出相关信息。
更多详情请参考下面链接:
https://blog.csdn.net/ZYC88888/article/details/81662671
在java的bin目录下打开jmc.exe这个程序。选中左侧的某个进程的MBean服务器,如下图:
通过左下侧的tab页切换,可以显示内存、线程、诊断命令等。
Flight Recorder(飞行记录器)
通过记录程序在一段时间内的运行情况,将记录结果进行分析和展示,可以更进一步对系统的性能进行分析和诊断。前提:要监控的程序必须带以下参数启动:
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
点击启动飞行器,进行一分钟的数据采集,显示常规的内存和CPU信息,还有代码、线程和I/O等比较重要的信息。
更多学习资料可以参考:
https://github.com/JDKMissionControl/jmc
最强大,产品化最好,但是收费。
安装教程:https://blog.csdn.net/shiyong1949/article/details/52574896
windows下的使用教程:https://blog.csdn.net/zljain/article/details/81777987
功能:快速找到性能瓶颈,改善接口性能。
火焰图是一个SVG格式的图片,图上的每个色块代表的是一个线程栈帧,纵轴方向从下往上表示的是函数调用栈,而横轴方向色块的宽度表示的是函数调用占用CPU的比例。
idea也支持打开火焰图(windows系统的不支持):
command + shift + alt + / ,快捷键打开下图:
选择Experimental features,对idea.profiler.enabled打勾,配置好,如下图:
执行携带Async Profiler的项
分析火焰图
y轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
x轴表示抽样数,如果一个函数在x轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。
火焰图就是看顶层的哪个函数占据的宽度最大。只要有”平顶”(plateaus),就表示该函数可能存在性能问题。
除了idea自带,可以在linux环境下载、编译、配置Async Profiler,参考如下:
https://www.jianshu.com/p/3d67d4eaf649