性能监控工具
jconsole
JConsole工具是JDK自带的图形化性能监控工具。并通过JConsole工具, 可以查看Java应用程序的运行概况, 监控堆信息、 元空间使用情况及类的加载情况等。
JConsole程序在%JAVA_HOM E%/bin目录下
或者你可以直接在命令行对他进行打印
会显示如下界面:
JConsole的连接方式
JConsole分为本地连接以及远程连接,一般我们本地连接在小型单体项目中用于本地分析较多,大型项目以及线上生产环境一般采用远程连接的方式。
本地连接:
Jconsole会在本地自动寻找当前的可监控进程,所以我们可以只要本地启动项目,就可以自动匹配并点击进去。
远程连接:
- 设置被监控的Java虚拟机启动的參数,一般的情况下,会有下面三个參数,各自是:
-Dcom.sun.management.jmxremote.port=1090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
也就是说,你需要在启动参数后面加上这几个参数
被监控的虚拟机启动以后,我们就能够其他电脑上通Jconsole进行远程连接。
连接的过程例如以下:
1.打开cmd,输入jconsole,就会出现jconsole控制台,
然后,我们输入要被监控的Java虚拟机的IP地址和port号,如果输入正确,连接button就上生效如果设计的监控port号为8082,连接的IP为:10.20.618.11(这个需要你防火墙以及端口都处于开放状态),例如以下图所看到的:
点击连接后,就会进入到正常的显示界面,说明就连接成功了。
JConsole的显示界面:
概述 :记录了“堆内存使用情况”、“线程”、“类”、“CPU使用情况”共四个资源的实时情况;
并且在时间范围可以选择从1分钟到1年的显示情况
内存 :可以选择查看“堆内存使用情况”、“非堆内存使用情况”、“内存池"PS Eden Space"”等内存占用的实时情况;界面右下角还有图形化的堆一级、二级、三级缓存(从左到右)占用情况,当然,如果三级缓存被全部占用也就是很可能内存溢出啦!这时可以去查看服务器的tomcat日志,应该会有“outofmemory"的异常日志信息。界面右上角处还提供了一个“执行GC”的手动垃圾收集功能,这个也很实用~而且界面下方还有详细的GC信息记录。,整个界面提供了关于垃圾收集必须的各项基础指标查询。
线程 :界面上部显示实时线程数目。下部还能查看到详细的每个进程及相应状态、等待、堆栈追踪等信息;
并且在右下角,我们还可以检测死锁的情况。如果当前线程没有出现死锁,那么会显示未出现死锁。
但是如果出现了死锁,这里也会进行相应的检测。会直接显示死锁的页面,并且我们可以通过点击对应的线程来查看死锁的信息。
类 :显示“已装入类的数目”、“已卸载类的数目”信息;
VM摘要 :显示服务器详细资源信息,包括:线程、类、OS、内存等;
MBean : 可在此页进行参数的配置。
MBean就是被JMX管理的资源。 一般有两种类型的MBean,标准的和动态的。 标准类型的MBean最简单,它能管理的资源(包括属性,方法,时间)必须定义在接口中,然后MBean必须实现这个接口。它的命名也必须遵循一定的规范,例如我们的MBean为User,则接口必须为UserMBean。 动态MBean必须实现javax.management.DynamicMBean接口,所有的属性,方法都在运行时定义。
这个一般情况下互联网交互式企业级开发用到的可能性没有那么高。因为现在JMX架构用得没那么多。
测试垃圾回收案例:
package com.example.jvmcase.test;
import com.google.common.collect.Lists;
import java.util.ArrayList;
public class JconsoleTest1 {
//将bytes设置为全局变量
public byte[] bytes = new byte[1024*1024];
//测试内存的变化情况
public static void main(String[] args) {
try {
Thread.sleep(3000);//为了能看到效果
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开始..");
fillHeap(1000);
}
public static void fillHeap(int count){
ArrayList<JconsoleTest1> jts = Lists.newArrayList();
for(int i=0;i<count;i++){
try {
//这里睡3S,出效果
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
jts.add(new JconsoleTest1());
}
}
}
监控JVM内存情况,发现持续不回收,内存持续上升。
接下来,将bytes放进构造函数中,变成局部变量。如果没有使用的情况下,垃圾回收器是会光顾。现在再去看内存情况,发现内存在垃圾回收时候会形成波峰。
public JconsoleTest2(){
//将bytes设置为局部变量
byte[] bytes = new byte[1024 * 1024];
}