深入理解JVM虚拟机12JVM性能管理神器VisualVM介绍与实战

36次阅读

共计 5252 个字符,预计需要花费 14 分钟才能阅读完成。

微信公众号【Java 技术江湖】一位阿里 Java 工程师的技术小站。作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点 Docker、ELK,同时也分享技术干货和学习经验,致力于 Java 全栈开发!(关注公众号后回复”Java“即可领取 Java 基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的 Java 学习指南、Java 程序员面试指南等干货资源)

                     

一、VisualVM 是什么?

    VisualVM 是一款免费的 JAVA 虚拟机图形化监控分析工具。

    1.  拥有图形化的监控界面。
    2. 提供本地、远程的 JVM 监控分析功能。
    3. 是一款免费的 JAVA 工具。
    4. VisualVM 拥有丰富的插件支持。

二、如何获取 VisualVM?

    VisualVM 官方网站:http://visualvm.java.net/

    VisualVM 各版本下载页面: http://visualvm.java.net/releases.html

     下载 VisualVM 时也应该注意,不同的 JDK 版本对应不同版本的 VisualVM,具体根据安装的 JDK 版本来下载第一的 VisualVM。

三、获取那个版本?

       下载版本参考:[](http://blog.csdn.net/chwshuan…Java 虚拟机性能管理神器 – VisualVM(4)– JDK 版本与 VisualVM 版本对应关系

备注:下列表中显示 1.3.6 版本只适合 JDK7 和 JDK8,可是我用 1.3.6 版还是可以监控 JDK1.6_45 的版本。

四、VisualVM 能做什么?

1. 显示 JAVA 应用程序配置和运行时环境。

显示 JAVA 应用程序 JVM 参数,系统属性,JVM 的信息和运行环境。

2. 显示本地和远程 JAVA 应用程序运行状态。

可以连接到远程服务器上运行的 JAVA 应用程序,监控应用程序的运行状态。

3. 监控应用程序的性能消耗。

可以监控到应用程序热点方法的执行单次时间、总耗时、耗时占比。

4. 显示应用程序内存分配,显示分析堆信息。

显示应用程序在运行时的编译时间、加载时间、垃圾回收时间、内存区域的回收状态等。

5. 监控应用程序线程状态和生命周期。

监控应用程序线程的运行、休眠、等待、锁定状态。

6. 显示、分析线程堆信息。

显示线程当前运行状态和关联类信息。

7. 支持第三方插件来分析 JAVA 应用程序。

另外还提供更多更强大、方便的第三方插件。

Java 虚拟机性能管理神器 – VisualVM(2)监控远程主机上的 JAVA 应用程序

    使用 VisualVM 监控远程主机上 JAVA 应用程序时,需要开启远程主机上的远程监控访问,或者在远程 JAVA 应用程序启动时,开启远程监控选项,两种方法,选择其中一种就可以开启远程监控功能,配置完成后就可以在本地对远程主机上的 JAVA 应用程序进行监控。

1. 远程服务器、应用程序配置

        1.1 配合 jstatd 工具提供监控数据  

        1.1.1 创建安全访问文件

        在 JAVA_HOME/bin 目录中,创建名称为 jstatdAllPolicy 文件(这个文件名称也可以顺便起,不过要与 jstatd 启动时指定名称相同),将以下内容拷贝到文件中。并保证文件的权限和用户都正确。

        grant codebase”file:${java.home}/../lib/tools.jar”{permission java.security.AllPermission;};

1.1.2 启动 jstatd 服务

        在 JAVA_HOME/bin 目录中,执行以下命令:

        ./jstatd -J-Djava.security.policy=jstatdAllPolicy-p 1099 -J-Djava.rmi.server.hostname=192.168.xxx.xxx

        jstatd 命令描述以及参数说明:

           jstatd 是一个基于 RMI(Remove Method Invocation)的服务程序,它用于监控基于 HotSpot 的 JVM 中资源的创建及销毁,并且提供了一个远程接口允许远程的监控工具连接到本地的 JVM 执行命令。

        -J-Djava.security.policy=jstatdAllPolicy 指定安全策略文件名称

         -p 1099  指定启动端口

         -J-Djava.rmi.server.hostname=192.168.xxx.xxx  指定本机 IP 地址,在 hosts 文件配置不正常时使用,最好加上。

1.2JVM 启动时配置远程监控选项

        在需要远程监控的 JVM 启动时,开启远程监控选项

        -Dcom.sun.management.jmxremote.port=1099
        -Dcom.sun.management.jmxremote.ssl=false
        -Dcom.sun.management.jmxremote.authenticate=false
        -Djava.rmi.server.hostname=192.168.xxx.xxx

2. 本地 VisualVM 配置

        在本地 VisualVM 的应用程序窗口,右键单击【远程】》【添加远程主机】》【主机名】中输入远程主机的 IP 地址,点击【高级设置】输入远程主机开启的监控端口,点击【确定】完成配置。

        如果一切正常,就可以看到远程主机上的 JAVA 应用程序了。

Java 虚拟机性能管理神器 – VisualVM(3)排查 JAVA 应用程序内存泄漏

1. 发现问题

    线上应用部署完成后,运行 1~2 天左右就会出现假死,或者某天早上 8~10 点高峰期间突然不处理数据了。由于在测试环境的压力测试没有做完全,也没有遇到相关问题。情况出现后对客户的使用造成很大影响,领导要求赶紧排查出问题原因!

2. 排查原因

        排查原因前,与运维沟通,了解线上服务器的运行状态,通过 ganglila 观察网络、CPU、内存、磁盘的运行历史状态,发现程序故障前,都有一波很高的负载,排查线上日志,负载来源在 8~9 点平台接入数据量成倍增加,通过与产品和市场人员分析,此时段是用户集中上班、接入平台的高峰时段,访问日志也显示,业务场景正常,无网络攻击和安全问题。属于产品业务正常的场景。

        排除了网络安全因素后,就从程序的运行内部进行排查,首先想到的获取 JVM 的 dmp 文件。获取 JVM 的 dmp 文件有两中方式:

        1. JVM 启动时增加两个参数,出现 OOME 时生成堆 dump: 

                -XX:+HeapDumpOnOutOfMemoryError

                生成堆文件地址:

                -XX:HeapDumpPath=/home/test/jvmlogs/ 

        2. 发现程序异常前通过执行指令,直接生成当前 JVM 的 dmp 文件,15434 是指 JVM 的进程号

                jmap -dump:format=b,file=serviceDump.dat    15434 

        由于第一种方式是一种事后方式,需要等待当前 JVM 出现问题后才能生成 dmp 文件,实时性不高,第二种方式在执行时,JVM 是暂停服务的,所以对线上的运行会产生影响。所以建议第一种方式。

3. 解决方案

        获取到 dmp 文件后,就开始进行分析。将服务器上的 dmp 文件拷贝到本地,然后启动本地的 VisualVM, 点击菜单栏【文件】选项,装入 dmp 文件

        打开 dmp 文件后,查看类标签,就能看到占用内存的一个排行。

        然后通过检查中查找最大的对象,排查到具体线程和对象。

        上列中的 com.ctfo.trackservice.handler.TrackHandleThread#4 就是重点排查对象。

        通过代码的比对,在此线程中,有调用 DAO 接口,负责将数据存储到数据库中。而存储到数据库中时,由于存储速度较慢,导致此线程中的数据队列满了,数据积压,无法回收导致了队列锁定,结果就是程序假死,不处理数据。

        通过进一步分析,发现数据库存储时有瓶颈,虽然当前是批量提交,速度也不快。平均 8000/ 秒的存储速度。而数据库有一个 DG(备份)节点,采用的是同步备份方式,即主库事务要等 DG 的事务也完成后才能返回成功,这样就会因为网络因素、DG 性能因素等原因导致性能下降。通过与 DBA、产品、沟通,将同步备份改为异步备份,实时同步改为异步(异步可能会导致主备有 10 分钟以内的数据延迟)。速度达到 30000/ 秒。问题解决。

        至此,通过 VisualVM 分析 java 程序内存泄漏到此结束。不过还有几个问题:1. 如果 dmp 文件较大,VisualVM 分析时间可能很久;另外,VisualVM 对堆的分析显示功能还不算全面。如果需要更全面的显示,就可以使用另外一个专业的 dmp 文件分析工具【Memory Analyzer (MAT)】,此工具可以作为 eclipse 的插件进行安装,也可以单独下载使用。如果有感兴趣的朋友,我个人建议还是单独下载使用。下载地址:http://www.eclipse.org/mat/   

 

Java 虚拟机性能管理神器 – VisualVM(4)查找 JAVA 应用程序耗时的方法函数

1. 为什么要监控?

        JAVA 程序在开发前,根据设计文档的性能需求,是要对程序的性能指标进行测试的。比如接口每秒响应次数要求 1000 次 / 秒,就需要平均每次请求处理的时间在 1ms 以内,如果需要满足这个指标,就需要在开发阶段对接口执行函数进行监控,也可以通过打印日志进行监控,从而统计对应的性能指标,然后可以根据性能指标的要求进行相应优化。

2. 那些方法函数需要监控?

        根据具体业务的场景和需求,主要集中在 IO 通讯、文件读写、数据库操作、业务逻辑处理上,这些都是制约性能的重要因素,所以需要重点关注。

        

3. 如何排查

        在研发环境,大部分会使用 syso 的方式或者日志方式打印性能损耗,如果代码没有加在运行时才想起来,或者想关注突然想起的函数,换做以前,是需要重启服务的,如果有 VisualVM 就可以直接查看耗时以及调用次数等情况。而不用打印、输出日志来查看性能损耗。

4. 如何处理

        对于性能损耗的函数,根据业务逻辑可以进行相应的优化,例如字符串处理、文件读写方式、SQL 语句优化、多线程处理等等方式。

       由于性能优化涉及的内容很多,这里就不深入了。主要是告诉大家通过 VisualVM 来排查问题的具体位置。

Java 虚拟机性能管理神器 – VisualVM(5)排查 JAVA 应用程序线程锁

1. JAVA 应用程序线程锁原因

        JAVA 线程锁的例子和原因网上一大堆,我也不在这里深入说明,这里主要是否讲如何使用 VisualVM 进行排查。至于例子可以看这里:http://blog.csdn.net/fengzhe0411/article/details/6953370 

这个例子比较极端,一般情况下,出现锁竞争激烈是比较常见的。

2. 排查 JAVA 应用程序线程锁

       启动 VisualVM,在应用程序窗口,选择对应的 JAVA 应用,在详情窗口》线程标签(勾选线程可视化),查看线程生命周期状态,主要留意线程生命周期中红色部分。

(1)绿色:代表运行状态。一般属于正常情况。如果是多线程环境,生产者消费者模式下,消费者一直处于运行状态,说明消费者处理性能低,跟不上生产者的节奏,需要优化对应的代码,如果不处理,就可能导致消费者队列阻塞的现象。对应线程的【RUNNABLE】状态。

(2)蓝色:代表线程休眠。线程中调用 Thread.sleep() 函数的线程状态时,就是蓝色。对应线程的【TIMED_WAITING】状态。

(3)黄色:代表线程等待。调用线程的 wait() 函数就会出现黄色状态。对应线程的【WAITING】状态。

(4)红色:代码线程锁定。对应线程的【BLOCKED】状态。

3. 分析解决 JAVA 应用程序线程锁

        发生线程锁的原因有很多,我所遇到比较多的情况是多线程同时访问同一资源,且此资源使用 synchronized 关键字,导致一个线程要等另外一个线程使用完资源后才能运行。例如再没有连接池的情况下,同时访问数据库接口。这种情况会导致性能的极具下降,解决的方案是增加连接池,或者修改访问方式。或者将资源粒度细化,类似 ConCurrentHashMap 中的处理方式,将资源分为多个更小粒度的资源,在更小粒度资源上来处理锁,就可以解决资源竞争激烈的问题。]

正文完
 0