您的位置:首页 > 运维架构

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

2017-03-14 11:37 706 查看
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       [<interval> [<count>]]

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导出堆

打开堆备份文件

查看线程栈,当前线程栈帧的局部变量(<Java Local>标记)

内存柱状图(对象类型数量、对象类型内存占有量)

各个对象的引用列表中穿梭查看
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属性的值

    [<alias>.]@<attribute> 获取堆内对象的额外属性简历的代理对象的访问,增强原有的对象功能

    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对象数组
使用代理对象的方法 [<alias>.]@<method>([<expression>,<expression>])
select s.getValueAt(2) from int [] s where (s.@length>2)     显示int数组中索引下标为2的数组内容
select OBJECTS s.@referenceArray.get(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

详见官方文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息