JVM监控分析方法总结,JVM监控分析工具推荐,JVM监控命令,JVM监控工具大全

JVM监控分析方法和工具网上介绍的很多,大家关心的大部分内容可能是“内存去哪儿了”,以下是个人的总结和心得。


分析方式:

实时监控

事后时候堆快照、线程栈分析

事后多个堆快照对比分析

飞行记录,一段时间的运行变化,有点像飞机出事后的“黑匣子”数据


观察方式:

命令行、日志文本文件观察分析

可视化图形界面分析


是否免费:

免费版。(整体上比商业版稍微逊色一点,但比较方便)

商业收费两种模式。(一般来说商业收费版的实时性高、功能更多、更强大、界面更舒服美观)


个人推荐分析工具:

推荐Jmc(JDK实时动态-Oracle Java Mission Control)、VisualVM(JDK实时动态)、MAT(静态dump)


监控工具-概要
1、OS命令
详见OS监控-linux.txt
ps -eLf PID   查看指定进程的线程列表


2、JDK自带命令
jps 查看java进程(类似于ps命令,但只列出java进程)
jinfo 查看和调整虚拟机参数
jstat 显示本地或远程虚拟机进程中的类装载/卸载情况、分代内存、垃圾收集、JIT编译/编译失败/最后一次编译失败的方法/编译耗时、保存堆快照
jmap 查看内存对象、空间使用率、保存堆快照、查看finalize执行队列、查看ClassLoader
jhat 堆快照文件*.hprof分析工具,指定堆文件进行分析,可以使用OQL查询(不建议使用)
jstack 查看线程堆栈快照 (死锁、上下文切换、死循环、请求外部资源导致长时间等待、长时间停顿或者出错代码位置)
jstatd 是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的java应用程序信息传递到远程计算机
jcmd  (查看虚拟机进程、打印线程栈、执行GC、代替jmap功能)
java hprof  性能统计工具,Java agent,监控CPU、堆、监控各个函数的CPU占用时间
vmstat
javap 分析Class文件字节码的工具


jps -l
jps -v
jps -m
jinfo -flag MaxTenuringThreshold 进程ID   (查看JVM当前参数值)
jinfo -flag MaxTenuringThreshold 进程ID  -XX:MaxTenuringThreshold=15 (设置JVM当前参数值)
jstat -gc -t java进程ID 1000 1       [ []]
jstat -gccause java进程ID    (最近一次GC的原因、当前GC的原因)
jstat -gcutil java进程ID    (显示垃圾收集信息)
jstat -gcnew java进程ID    (查看新生代的详细信息)
jstat -gcnewcapacity java进程ID    (查看新生代各区的容量信息)
jstat -gcold java进程ID    (查看老年代GC的概况)
jstat -gcoldcapacity java进程ID    (查看老年代的容量信息)
jstat -gcpermcapacity java进程ID    (查看永久区的使用情况)
jmap -histo java进程ID > E:\cc.txt    (导出堆到文件)
jmap -dump:format=b,file=E:\HeapDump.hprof java进程ID (导出堆快照)
jmap -permstat java进程ID (查看系统的ClassLoader信息)
jmap -finalizerinfo java进程ID (查看堆积在finalizer队列中的对象)
jhat E:\HeapDump.hprof (启动完毕之后,访问http://localhost:7000、支持OQL查询)(不建议使用)
jstack -l java进程ID > E:\thead.stack     (导出线程栈到文件)


jstatd   注意(先启动jstatd,再启动tomcat,这是jmx的tomcat即可以查看CPU,也可以查看Visual GC的内存回收情况)
远程服务器上的JVM监控就需要一些额外的配置了。目前VisualVM支持两种监控方法:Jstatd方法和基于JMX的方法。
Jstatd方法是利用后台的RMI守护进程来实现对远程JVM的监控。首先创建一个监控策略文件。
JMX方式是我们监控应用服务器常用的方,连接JMX方法首先需要在Java端进行一些配置。
"JVM不受此JVM支持" http://blog.csdn.net/autfish/article/details/51326340
/home/dev/soft/jdk1.8/bin/jstatd.all.policy
jstatd.all.policy文件内容
grant codebase "file:${java.home}/../lib/tools.jar" {
    permission java.security.AllPermission;
};
cd $JAVA_HOME/bin && ./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=172.16.1.18 &
jps IP:1099
jstat -gcutil java进程ID@IP:1099


jcmd -l 列出虚拟机列表
jcmd java进程ID help   (帮助)
jcmd java进程ID Thread.print > E:\thread.stack    (打印线程栈信息)
jcmd java进程ID GC.head_dump E:\HeadpDump.hprof      (保存堆快照)
jcmd java进程ID GC.class_histogram
jcmd java进程ID VM.system_properties (查看系统信息)
jcmd java进程ID VM.flags     (查看jvm启动参数)
jcmd java进程ID PerfCounter.print (查看性能统计相关数据、活动线程数、活动线程峰值)
java -agentlib:hprof=help    (帮助)
java -agentlib:hprof=cpu=times,interval=10,file=E:\cpu.txt java进程ID    (java函数的调用前后记录函数的执行时间,进而计算函数的执行时间)
java -agentlib:hprof=heap=sites,interval=10,file=E:\heapMemory.txt java进程ID    (每个跟踪点上的类所占内存百分比)
java -agentlib:hprof=heap=dump,format=b,file=E:\heapDump.txt java进程ID    (保存堆快照)
vmstat 统计线程上下文切换次数


3、JDK自带工具-JConsole     (图形化虚拟机监控工具)
优势(检测死锁、执行GC、非堆内存细化显示:Metaspace、Code Cache、Compressed Class space)
查看堆内存使用情况
查看线程数量
线程栈
线程检测死锁按钮
分代内存大小
分代内存比率
类加载数量
VM概要


4、JDK自带工具-JVisualvm (可视化性能监控工具,安装Visual GC插件之后,才能查看分代各区内存实时监控)
VisualVM连接远程服务器有两种方式:JMX和jstatd
jstatd不支持CPU监控


可替代jdk命令
可替代JConsole
工具-插件,可安装插件
分代各区内存实时监控(安装Visual GC插件之后才能看,效果比JConsole直观)
显示进程ID
导出dump堆快照
导出线程堆栈
查看单个线程堆栈
显示死锁
实时函数CPU耗时排名
实时线程CPU耗时排名
实时对象类型的内存分配排名
实时线程内存分配排名
按类包路径查找、设置排除、刷新频率
2个堆快照文件比较(与另一个堆转储比较 按钮)
对象类型的所有实例-选择实例-追踪root调用位置
Tracer插件, Probes实时波浪图,Probes选项自定义
BTracer插件,打印调用堆栈、参数、返回值、性能监视、定位连接泄露、内存泄露、解决多线程竞争
BTracer插件,编写BTracer脚本,通过字节码注入动态监控系统的运行情况,BTracer用户手册
BTracer插件,监控指定函数耗时
BTracer插件,监控指定函数参数
BTracer插件,监控指定对象的属性值
BTracer插件,定时触发,周期性地执行某一行为
BTracer插件,指定在某个类的第N行代码触发执行一个函数
BTracer插件,指定在某个类的第N行代码,获取对象实例的字段信息
BTracer插件,获取函数内部调用链
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class TracingScript {
@TLS
    private static long startTime=0;
    
    @OnMethod(clazz="/.+/",method="/visitWeb/")
    public static void startMethod(){
        startTime=timeMillis();   
    }
    
    @OnMethod(clazz="/.+/",method="/visitWeb/",location=@Location(Kind.RETURN))
    public static void endMethod(){
         print(strcat(strcat(name(probeClass()), "."), probeMethod)));
         print("[]");
         print(strcat("Time taken:", str(timeMillis()-startTime)));
         print("[]");
    }
}
OQL控制台,与MAT的不一样
操控visualvm的文档,有MAT的OQL功能,有集合/统计函数,支持javascript、json风格语法
支持自定义插件开发,自动分析堆和计算
控制台支持直接使用javascript代码进行编程
非常灵活,visualvm的OQL比MAT的OQL的功能强大很多


5、商业工具-JDK-jmc (Oracle Java Mission Control)
来自JRockit的礼物,界面特别美观舒服
查看MBean
JMX控制台-概览-实时数据、增加监控仪表盘
飞行记录(最具特色,记录程序在一段时间内的运行情况,相当于飞机失事后的黑匣子,一段时间内的内存、I/0、Socket、线程、CPU、耗时方法及其调用树)
触发器弹出框提示,CPU、内存、线程复制过高或者过低
仪表盘面板自定义增加监控项,类似于Visualvm-Tracer-probes
DTracer


6、第三方工具-MAT
MAT的10个小技巧http://www.jianshu.com/p/759e02c1feee
把java本地进程ID导出堆
打开堆备份文件
查看线程栈,当前线程栈帧的局部变量(标记)
内存柱状图(对象类型数量、对象类型内存占有量)
各个对象的引用列表中穿梭查看
Incomming References(入引用-引用到该对象的对象)
Outgoing References(出引用-被该对象引用的对象)
小技巧:
当目的不明确时,可以直接定位到RetainedHeap最大的Object,Select incoming references ,查看引用链,定位到可疑的对象然后Path to GC Roots进行引用链分析
如果大对象筛选看不出区别,可以试试按照class分组,再寻找可疑对象进行GC引用链分析
直接按照包名直接查看GC引用链,可以一次性筛选多个类,但是如下图所示,选项是 Merge Shortest Path to GCRoots,这个选项具体不是很明白,不过也能筛选出存在GC引用链的类,这种方式的准确性还待验证。

Shallow Heap (浅堆)
是指一个对象所占用的内存大小;
不包括其内部引用对象的大小
和对象持有的 内容无关
Retained Heap (深堆)
一个对象被GC回收后,可以真实释放的内存大小;
对象A的保留集指当对象A被垃圾回收后,可以被释放的所有的对象集合(包括对象A本身),即对象A的保留集可以被认为是只能通过对象A呗直接或间接访问到的所有对象的集合。
是指仅被对象A所持有的对象的集合(Retained Set)
是指对象的保留集中所有的对象的浅堆大小之和
是指只能通过该对象访问到的(直接或间接)所有对象的浅堆之和,即对象被回收之和,可以释放的真实空间
对象的实际大小
一个对象所能触及的所有对象的浅堆大小之和
支配树(Dominator Tree)
支配树体现了对象实例间的支配关系,是基于对象间的引用图所建立的
对象A的子树(所有被对象A支配的对象集合)表示对象A的保留集(Retained set),即深堆
如果对象A支配对象B,那么对象A的直接支配者也支配对象B
支配树的边与对象引用图的边不直接对应
支配树(Dominator Tree)在MAT里的操作:选择一个对象A->右键->Java Basics->Open In Dominator Tree,显示的内容就是当对象A呗回收,也会一并回收的所有对象
MAT分析Tomcat内存溢出
MAT实战分析https://www.cc362.com/content/QzpvBlANp4.html
overview左上角Size是堆占用大小
鼠标放到饼图上,显示深堆大小、深堆对象的类
单击饼图->List objets->with outgoing references
OQL (visualvm的OQL比MAT的OQL功能强大)
类似于SQL
select * from com.youren.common.controller.TempController
投影、去重、只查保留集
select AS RETAINED SET * from com.youren.common.controller.TempController
select * from 内存地址 (获取内存地址的方式:选择对象->右键->copy->Address)
select * from "geym\.zbase\..*" (引号内是正则表达式)
select * from INSTANCEOF java.util.AbstractCollection (返回指定类的所有子类实例)
select * from OBJECTS "geym\.zbase\..*" (引号内是正则表达式,OBJECTS返回类的信息)
where like and or
select * from char[] s where s.@length>10    返回长度大于10的char数组
select * from java.lang.String s where toString(s) like ".*java.*"    返回包含"java"子字符串的所有字符串,like操作符的操作参数为正则表达式
    select * from java.lang.String s where s.value!=null        返回所有value域不为null的字符串
    select * from java.util.Vector v where v.elementData.@length>15 and v.@retainedHeapSize>1000 返回数组长度大于15,并且深堆大于1000字节的所有Vector对象
    select toString(f.path.value) from java.io.File f  返回File对象的path属性的值
    [.]@ 获取堆内对象的额外属性简历的代理对象的访问,增强原有的对象功能
    select s.toString(), s.@objectId, s.@objectAddress from java.lang.String s  显示String对象的内容、objectId、objectAddress
    select f.@objectId, f.@objectAddress, f.@class, f.@clazz, f.@usedHeapSize, f.@retainedHeapSize, f.@displayName from java.io.File f   显示File对象ID、对象地址、代理对象的类型、类的类型、对象的浅堆大小、对象的深堆大小、对象的显示名称
select v.elementData.@length from java.util.Vector v  显示java.util.Vector内部数组的长度
内置属性
@objectId
@objectAddress
@class
@clazz
@usedHeapSize
@retainedHeapSize
@displayName
@classLoaderId   
@length    
@valueArray基本类型数组   
@referenceArray对象数组
使用代理对象的方法 [.]@([,])
select s.getValueAt(2) from int [] s where (s.@length>2)     显示int数组中索引下标为2的数组内容
select OBJECTS [email protected](2) from java.lang.Object[] s where (s.@length>2)    显示对象数组中索引下标为2的对象
select * from INSTANCEOF java.util.Vector 显示所有的java.util.Vector对象实例及其子类型的对象实例
    select c, classof(c).isArrayType() from ${snapshot}.getClasses() c      显示当前对象是否是数组
    代理对象方法
    getClasses()
    getCalssesByName(String name,boolean includeSubClasses)
    hasSuperClass()
    isArrayType()
    getObjectAddress()
    getValueAt(int index)
    get(int index)
    内置函数
    toHex(number)转为16进制
    toString(object)转为字符串
    dominators(object)取得直接支配对象,与dominatorof相反
    dominatorof(object)取得给定对象的直接支配者,用于获得直接支配当前对象的对象,与dominators相反
    outbounds(object)取得给定对象引用的对象
    inbounds(object)取得引用给指定对象的对象
    classof(object)取得当前对象的类
select toString(s) from java.lang.String s where ((s.value.@length==15) and (s.value!=null))     显示所有长度为15的字符串内容
select OBJECTS dominators(s) from geym.zbase.ch7.heap.Student s 显示所有geym.zbase.ch7.heap.Student对象的直接支配对象


7、商业工具-JProfiler
详见官方文档


8、第三方工具-GChisto
分析GC日志的离线分析工具。 
GChisto 以表格和图形化的方式展示 GC 次数、 持续时间等, 提高了分析 GC 日志的效率
GC 的次数、 GC 的时间、 GC 的开销、 最大 GC 时间和最小 GC 时间
切到 GC Pause Distribution 选项卡, 可以查看 GC 停顿的详细分布, x 轴表示垃圾收集停顿时间, y 轴表示是停顿次数
切换到 GC Timeline 选项卡, 可以显示整个时间线上的垃圾收集, 以便于按时间去查找应用日志(tomcat 日志等), 去了解峰值时系统发生了什么
详见http://blog.csdn.net/wenniuwuren/article/details/50760259


9、Tomcat Manager
详见官方文档


10、第三方工具-NetBeans Profiler
详见官方文档


你可能感兴趣的:(JVM,jvm,java,性能监控工具,性能分析)