一、JVisualVM是什么
简介
JVisualVM 是一个集成了命令行 JDK 工具和轻量级分析功能的可视化工具,专为开发和生产环境使用而设计。
官方地址:https://VisualVM.github.io/
JVisualVM 已作为 Java JVisualVM 在 Oracle JDK 6~8 中分发。它已在 Oracle JDK 9 中停止。
独立的VisualVM可以从官网下载,可以在任何兼容的JDK版本上运行。
功能介绍
JJVisualVM 使用各种技术(包括 jvmstat、JMX、Serviceability Agent (SA) 和 Attach API)监视和排除许多供应商在 Java 1.4+ 上运行的应用程序。JJVisualVM 完美地满足应用程序开发人员、系统管理员、质量工程师和最终用户的所有要求。包括以下功能:
- 显示本地和远程 Java 进程 JVisualVM 自动检测并列出本地和远程运行的 Java 应用程序(jstatd 必须在远程主机上运行)。您还可以通过 JMX 连接手动定义应用程序。
- 显示进程配置和环境 对于每个进程,JVisualVM 显示基本的运行时信息:PID、主类、传递给 java 进程的参数、JVM 版本、JDK 主页、JVM 标志和参数以及系统属性。
- 监控进程性能和内存 JVisualVM 监控应用程序 CPU 使用率、GC 活动、堆和元空间/永久代内存、已加载类的数量和正在运行的线程。
- 可视化进程线程 在 Java 进程中运行的所有线程与聚合的运行、睡眠、等待、停放和监控时间一起显示在时间轴中。
- 配置文件性能和内存使用情况 JVisualVM 提供用于分析应用程序性能和内存管理的基本分析功能。采样和仪器分析器都可用。
- 获取并显示线程转储 JVisualVM 获取并显示线程转储,以便立即了解目标进程中发生的情况。多个进程的同时线程转储有助于发现分布式死锁。
- 获取和浏览堆转储 JVisualVM 创建和查看按需或在 OutOfMemoryError 上创建的 .hprof 内存快照,以帮助发现低效的堆使用和调试内存泄漏。
- 分析核心转储 JVisualVM 能够从核心转储中读取有关崩溃的 Java 进程及其环境的基本信息,并提取并打开包含的线程和堆转储。
- 离线分析应用程序 JVisualVM 能够将应用程序配置和运行时环境连同所有获取的线程转储、堆转储和分析器快照一起保存到单个应用程序快照中,以后可以脱机处理。
二、安装和启动
下载
官方下载地址:https://github.com/oracle/visualvm
启动
安装有jdk6-jdk8环境的机器,命令行直接输入jvisualvm启动。
或者去官网下载独立的VisualVM客户端,解压之后直接启动。
启动成功后,如果有本地的java进程可以直接看到。
中文设置
独立安装包网上说有多国语言版的,但是我在官网没有找到。
如果用jdk自带的,默认就是中文的。
字体大小设置调整
快捷方式启动,目标target后面加上 ** --fontsize 20s**
三、监控
监控本机
启动JvisualVM即可自动监控本机的java进程,不要进行参数配置。
Idea有时候连接不上,添加 -Djava.net.preferIPv4Stack=true
参数。
注:debug时连接不上。idea中debug模式运行停在断点时,jconsole不能连接该进程。与jvm参数之类的没有关系。
visualVM连接后的监控面板如下:
点击一个进程,就可以看到该进程的概述信息,该进程的JVM参数以及系统属性等信息都能够查看到。
监控远程主机
配置启动参数
远程监控的时候才需要配置参数
-Dcom.sun.management.jmxremote #添加一个jmx远程连接属性,可以省略
#远程监控连接端口号
-Dcom.sun.management.jmxremote.port=23929
#当存在防火墙等网络访问限制时,可通过 com.sun.management.jmxremote.rmi.port 参数指定 RMI 连接器所使用的端口并进行开放。在这种场景下,必须设置此参数。com.sun.management.jmxremote.rmi.port 使用的端口,可以与 com.sun.management.jmxremote.port 指定的端口相同,这样仅开放一个端口就可以了。
-Dcom.sun.management.jmxremote.rmi.port=23929
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
#内网IP,远程监控时候配置为本机的内网IP 为需要远程连接时必须设置的参数,否则只能从本地对应用进行监控,无法从远程机器进行连接。
-Djava.rmi.server.hostname=192.168.1.150
jar包的启动命令:
java -Dcom.sun.management.jmxremote.port=23929 -Dcom.sun.management.jmxremote.rmi.port=23929 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.1.150 -jar netty-1.0-SNAPSHOT.jar
tomcat配置:
配置带身份验证的参数
在远程服务器上的JDK根目录下的/jre/lib/management文件夹下,将jmxremote.password.template文件复制一份jmxremote.password,然后打开jmxremote.password文件,配置权限文件为600。
将里面的这两行注释去掉,monitorRole和controlRole就是用户名,QED和R&D分别是密码,最后更改了密码,当然和可以使用同样的格式自己添加用户,对于用户的权限是在jmxremote.access文件中配置的,这两个角色的权限默认已经配置了,如果自己添加的用户,你需要自己在这个文件中添加相应的配置,我们暂时就使用controlRole这个角色,因为他的权限比较多:
#monitorRole QED
#controlRole R&D
启动时候-Dcom.sun.management.jmxremote.authenticate=true,需要设置为true。
添加远程主机
添加JMX连接,端口号为启动时候指定的端口号,没有密码验证。
远程主机无法连接处理办法
- 监控远程主机之前参考配置参数设置,并且先用curl或者telnet命令测试,远程端口是否正常可访问,若不能访问调整防火墙、安全组等设置。
- 网上查到JMX除了指定的端口外,还需要监听一到两个随机端口,所以要在安全组里或者和防火墙把这几个端口也开放,可以lsof -i|grep {pid}或者sudo netstat -nap | grep 进程号 命令得到监听的其他端口。
- 对于有硬件防火墙做Net转换的,curl远程端口正常,但是通过外网ip也无法访问的暂时不知道如何处理,有可能需要把/etc/hosts配置为外网IP。 截取歪果仁的两种办法:
- 检查服务器公共IP
netstat -lp | grep [pid from step 4]
- 使用JVM参数:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=[jmx port]
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=[server ip from step 1]
3. 运行应用程序
4. 查找正在运行的Java进程的进程ID。
5. 检查JMX / RMI使用的所有端口。
netstat -lp | grep [pid from step 4]
6. 打开防火墙上第5步中的所有端口。
另外一种:
通过更改jvisualvm代理设置(工具->选项->网络)解决了这个问题。 将选项更改为“无代理”后,便可以连接。 jvm使用以下选项启动:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=2222
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=<external_IP_of_server>
然后,当添加jmx连接时,我指定了“ external_IP_of_server:2222”