JVM是Java Virtual Machine(Java虚拟机)的缩写。JVM的分析工具也有很多,本文重点讲一下
javosize,nss的javamethod、btrace、
VisualVM
等工具进行定位性能问题的方法。因作者水平有限,还请大家对不足之处进行指正,共同学习。
一、Javamethod
JavaMethod是杭研的哨兵系统nss中可以接入查看类中方法的方法名、调用次数、耗时等的一个有用工具,具体接入方式如下:
1. 首先要去op工单上面申请机器接入到哨兵(可以让运维PE帮忙看一下要接入哪个集群);
2. 然后要下载 sentry-javaagent-home.zip,地址:
http://doc.hz.netease.com/pages/viewpage.action?pageId=42557026
3. 用unzip解压后进入文件夹,
sentry-javaagent-premain-2.0.0.jar ------ java agent的主体部分。目前用2.0.0版本,以后变化的可能性非常小。
sentry.properties ------ 基础配置文件,主要需要配置的appName和instance ,appName用在cmdb中创建的应用的名字(具体请联系应用运维),instance 默认 default。其他的一些配置,一般无需修改。
javaMethod.xml------ 配置需要拦截的java方法,配置方法见“java方法监控”一章
url.xml url------ 配置需要拦截的java方法,配置方法见“URL的监控”一章
修改配置文件,具体可以参考b-qa17的配置
4.把sentry-javaagent-collector-0.2.34.jar这个jar包放置在 /home/appuser/urs/regzj_dl2/webroot-urs-regzj-perftest-Ins1/WEB-INF/lib
目录下面。如果不是最新的版本,可以在maven里面用
<dependency>
<groupId>com.netease.sentry</groupId>
<artifactId>sentry-javaagent-collector</artifactId>
<version>0.2.34</version>
</dependency>
进行更新一下,然后去相应的maven仓库里面找到这个jar包就可以了
5. 修改jvm参数,在omad上面部署的tomcat应用可以这样:
即下面这两行,注意目录修改成自己相应的:
-javaagent:/home/appuser/shaobing/sentry-javaagent-home/sentry-javaagent-premain-2.0.0.jar -Dsentry_collector_libpath=/home/appuser/urs/regzj_dl2/webroot-urs-regzj-perftest-Ins1/WEB-INF/lib
这一步完成后,会产生一个/home/appuser/sentry-javaagent 文件夹,从里面可以看到日志;注意:下面的这个WEB-INF/lib目录下必须包含 sentry-javaagent-collector-0.2.24.jar 这个jar包。
6. sentry.properties这个文件【/home/appuser/shaobing/sentry-javaagent-home 这个目录下面】的配置
#isJavaMethodCollectorEnable=false 这个应该注释掉,默认的是true的,就是开启拦截的这个功能;
配置成功后,可以在哨兵系统上看到如下的信息,在脚本运行一段时间后,就可以在哨兵的页面刷新看到所拦截到的javamethod的信息:
二、HouseMD
HouseMD 是一款非常敏捷的Java进程运行时的诊断调式命令行工具, 它具备安全易用高效的特点, 让它非常适合在要求严格的线上(生产)环境中使用。HouseMD的使用方法如下:
housemd_2.9.2-0.2.4.jar包,导入到linux中,可以用top,jps查看PID找到PID后,用命令:
java -Xbootclasspath/a://usr/lib/jvm/j2sdk1.6-oracle/lib/tools.jar -jar housemd_2.9.2-0.2.4.min.jar PID
HouseMD经常被用来监控耗时较长的方法,配合线程堆栈的使用,根据堆栈信息自下而上的依次监控每个类的方法。堆栈信息中的最下面的类的方法中的耗时时间包括上面列出来的类的方法的耗时时间,则用housemd定位出来的时间差可以确定哪个方法最为耗时,同时也可以同时用哨兵系统中的javmethod来确认:
用命令 trace -d Login.l 就可以把输出的时间等日志输出到,/tmp/trace/21659@hzbxs-qa17 这个目录下:
2016-01-25 19:20:16 8ms [http-bio-8181-exec-730] com.netease.urs.regzj.common.cache.NkvImpl@281fc71c com/netease/urs/regzj/common/cache/NkvImpl.setCount [lt_succ_un_urstestr150o31ieim@163.com 1 1800] void
每列含义: 日期,时间戳,调用耗时,调用线程名。调用方法的自身对象,调用方法全名,调用方法参数值列表,返回值(或异常)。
三、BTrace
具体
BTrace
工具的使用详情,可以参考性能测试组的张伟杰的《
BTrace
简明使用手册》,介绍非常详细。
四、VisualVM
VisualVM 是一个性能分析工具,自从 JDK 6 Update 7 以后已经作为 Oracle JDK 的一部分,位于 JDK 根目录的 bin 文件夹下。VisualVM 自身要在 JDK6 以上的版本上运行,但是它能够监控 JDK1.4 以上版本的应用程序。VisualVM能够通过工具-插件选项安装插件扩展其功能。
功能介绍
VisualVM能够实时的监控JVM的CPU进和内存的使用情况,线程的状态,还能够对CPU和内存进行实时的profile,另外还具备快照功能。
CPU 分析
VisualVM 能够监控应用程序在一段时间的 CPU 的使用情况,显示 CPU 的使用率、方法的执行效率和频率等相关数据帮助我们发现应用程序的性能瓶颈。我们可以通过 VisualVM 的监视标签和 Profiler 标签对应用程序进行 CPU 性能分析。在监视标签内,我们可以查看 CPU 的使用率以及垃圾回收活动的CPU占用率。如果CPU利用率异常的高,可以通过 Profiler 标签的 CPU 性能分析功能进行详细的分析。如果垃圾回收活动过于频繁,占用了较高的 CPU 资源,则需要对内存进行分析。
图 1. CPU 使用情况
在这张图中,可以看到CPU整体利用率比较高,达到80%左右,同时垃圾回收活动的CPU使用率高达10%,表明GC很频繁需要对内存进行分析。如果CPU利用率比较高但是TPS比较低,或者想知道CPU消耗在哪些方法上,可以使用CPU Profile功能。
在 Profiler 标签,点击“CPU”按钮启动一个 CPU 性能分析会话 ,VisualVM 会检测应用程序所有的被调用的方法,然后把每个被调用方法的总的执行时间按照运行时长展示出来。
图 2. CPU 性能分析结果
输出的内容中的信息有热点方法,自用时间占比,自用时间,自用时间(CPU).其中的自用时间是方法自身执行的时间,不包括调用其他方法的时间。自用时间(CPU)是方法自身消耗CPU的时间。自用时间比较高,表示方法的总体的执行时间比较长,可能是方法单次执行的时间比较短,但是执行的次数比较多,或者执行次数不多,但单次的执行耗时间。自用时间(CPU)比较高表示方法比较耗CPU。对于CPU密集型的应用,热点方法的自用时间和自用时间CPU一般很接近。通过这个监控可以定位到消耗CPU的热点方法。
定位到热点方法以后,有时需要知道方法的调用路径,这个时候可以使用VisualVM的快照功能。生成的快照的展示有几个维度,调用树,热点,组合,信息。最直观的是热点方法。如果是CPU消耗比较高,在热点方法的视图中按照自用时间(CPU进行排序),选择需要追踪的方法,后键点击反向跟踪就可以得到方法调用的路径。
图 3. 热点方法的反响跟踪
上图中显示了热点方法的时间,时间(CPU),调用次数,以及调用的来源。通过这个图很清楚的知道方法的调用路径,以及调用次数之间的关系,也可以定位是否有循环调用。
内存分析
VisualVM 通过检测 JVM 中加载的类和对象信息等帮助我们分析内存使用情况,我们可以通过 VisualVM 的监视标签和 Profiler 标签对应用程序进行内存分析。在监视标签内,我们可以实时监控到JVM整个堆的变化情况
图 4. 内存堆使用情况
如果观察到堆内存发现已使用堆内存不断增加,直至接近最大堆内存,且没有回收的迹象,或有回收,但回收的效率很低,回收完堆的占用依然比较大,如果出现这种情况,可以怀疑是出现内存泄露。如上图中的红色箭头所指示的变化趋势,回收后堆的占用不断增加.
对Heap的详细监控可以加载VisualGC插件
图5. VisualGC动态视图
VisualGC动态视图动态展示了Old区,Eden区,s0/s1区的变化.通过观察这些区的变化来判断是否有内存问题。如果内存出现问题,可以使用jmap生成HeapDump,再通过MAT来离线分析。
线程分析
Java 语言能够很好的实现多线程应用程序。当我们对一个多线程应用程序进行调试或者开发后期做性能调优的时候,往往需要了解当前程序中所有线程的运行状态,是否有死锁、热锁等情况的发生,从而分析系统可能存在的问题。
在 VisualVM 的监视标签内,我们可以查看当前应用程序中所有活动线程和守护线程的数量等实时信息。
图 6. 活跃线程情况
这里重点关注下已启动的线程总数,稳定运行的JVM,这个值变化不大,如果增加的比较块,说明应用很可能在不断的创建新的线程,这可能导致Native Space的OOM
VisualVM 的线程标签提供了三种视图,默认会以时间线的方式展现。另外两种视图分别是表视图和详细信息视图。
时间线视图上方的工具栏提供了缩小,放大和自适应三个按钮,以及一个下拉框,我们可以选择将所有线程、活动线程或者完成的线程显示在视图中。
图 7. 线程时间线视图
线程的时间线图实时显示了线程的状态。重点关注Blocked的线程,也就是颜色是红色的线程。如果有大量线程的状态处于红色或者部分线程的状态长期处于红色,说明有线程被Blocked.可以使用右上角的线程 dump功能生成dump文件来分析
本文来自网易实践者社区,经作者齐红方授权发布。