Java 监控基础 - 使用 JMX 监控和管理 Java 程序
点赞再看,动力无限。Hello world : ) 微信搜「程序猿阿朗 」。
本文 Github.com/niumoo/JavaNotes 和 未读代码网站 已经收录,有很多知识点和系列文章。
此篇文章介绍 Java JMX 技术的相关概念和具体的使用方式。
当前文章属于Java 性能分析优化系列文章,点击可以查看所有文章。
1. JMX 是什么?
Java Management Extensions(JMX)技术是 Java SE 平台的标准功能,提供了一种简单的、标准的监控和管理资源的方式,对于如何定义一个资源给出了明确的结构和设计模式,主要用于监控和管理 Java 应用程序运行状态、设备和资源信息、Java 虚拟机运行情况等信息。 JMX 是可以动态的,所以也可以在资源创建、安装、实现时进行动态监控和管理,JDK 自带的 jconsole 就是使用 JMX 技术实现的监控工具。
使用 JMX 技术时,通过定义一个被称为 MBean 或 MXBean 的 Java 对象来表示要管理指定的资源,然后可以把资源信息注册到 MBean Server 对外提供服务。MBean Server 充当了对外提供服务和对内管理 MBean 资源的代理功能,如此优雅的设计让 MBean 资源管理和 MBean Server 代理完全独立开,使之可以自由的控制 MBean 资源信息。
JMX 不仅仅用于本地管理,JMX Remote API 为 JMX 添加了远程功能,使之可以通过网络远程监视和管理应用程序。
2. 为什么使用 JMX 技术?
JMX 技术为 Java 开发者提供了一种简单、灵活、标准的方式来监测 Java 应用程序,得益于相对独立的架构设计,使 JMX 可以平滑的集成到各种监控系统之中。
下面列举几项 JMX 的具体优点:
- 开箱即用的监控功能,JMX 是 Java SE 的标准部分,提供了资源管理、服务托管、远程监控等管理基础功能,都可以直接启用。
- JMX 技术提供了一种通用的、标准的资源、系统、应用程序、网络的管理方式,不仅可以本地使用、远程使用;还可以扩展到其他场景,如 Java EE 应用等。
- JMX 技术提供了对 JVM 状态的监测功能,JMX 已经内置了对 JVM 的监测功能,并且可以监控和管理 JVM,十分方便。
- JMX 架构设计优秀,组件化的设计可以自由的扩展。
- JMX 技术严格遵守 Java 现有规范如 JNDI 规范。
- JMX 可以自由的与其他管理解决方案集成,得益于开放的 JMX API,可以通过 web 服务管理 JMX 中的资源。
3. JMX 的技术架构
JMX 技术架构主要有资源管理(MBean/MXBean)模块,资源代理模块(MBean Server),远程管理模块(Remote API)组成 ,下面的图片来自维基百科,很好的展示了三个模块之间的关系。
3.1. 资源管理 MBean
资源管理在架构中标识为资源探测层(Probe Level),在 JMX 中, 使用 MBean 或 MXBean 来表示一个资源(下面简称 MBean),访问和管理资源也都是通过 MBean,所以 MBean 往往包含着资源的属性和操作方法。
JMX 已经对 JVM 进行了多维度资源检测,所以可以轻松启动 JMX 代理来访问内置的 JVM 资源检测,从而通过 JMX 技术远程监控和管理 JVM。
下面列举 JMX 对 JVM 的资源检测类,都可以直接使用。
资源接口 | 管理的资源 | Object Name | VM 中的实例个数 |
---|---|---|---|
ClassLoadingMXBean | 类加载 | java.lang:type= ClassLoading | 1个 |
CompilationMXBean | 汇编系统 | java.lang:type= Compilation | 0 个或1个 |
GarbageCollectorMXBean | 垃圾收集 | java.lang:type= GarbageCollector, name=collectorName | 1个或更多 |
LoggingMXBean | 日志系统 | java.util.logging:type =Logging | 1个 |
MemoryManagerMXBean | 内存池 | java.lang: typeMemoryManager, name=managerName | 1个或更多 |
MemoryPoolMXBean | 内存 | java.lang: type= MemoryPool, name=poolName | 1个或更多 |
MemoryMXBean | 内存系统 | java.lang:type= Memory | 1个 |
OperatingSystemMXBean | 操作系统 | java.lang:type= OperatingSystem | 1个 |
RuntimeMXBean | 运行时系统 | java.lang:type= Runtime | 1个 |
ThreadMXBean | 线程系统 | java.lang:type= Threading | 1个 |
下面的代码示例演示了使用 JMX 检测 JVM 某些信息的代码示例。
package com.wdbyte.jmx;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryManagerMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.util.List;
import java.util.stream.Collectors;
/**
* JMX JVM
*
* @author https://www.wdbyte.com
*/
public class JavaManagementExtensions {
public static void main(String[] args) {
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
String osName = operatingSystemMXBean.getName();
String osVersion = operatingSystemMXBean.getVersion();
int processors = operatingSystemMXBean.getAvailableProcessors();
System.out.println(String.format("操作系统:%s,版本:%s,处理器:%d 个", osName, osVersion, processors));
CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
String compilationMXBeanName = compilationMXBean.getName();
System.out.println("编译系统:" + compilationMXBeanName);
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
long max = heapMemoryUsage.getMax();
long used = heapMemoryUsage.getUsed();
System.out.println(String.format("使用内存:%dMB/%dMB", used / 1024 / 1024, max / 1024 / 1024));
List<GarbageCollectorMXBean> gcMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
String gcNames = gcMXBeans.stream()
.map(MemoryManagerMXBean::getName)
.collect(Collectors.joining(","));
System.out.println("垃圾收集器:" + gcNames);
}
}
运行可以得到如下结果:
操作系统:Mac OS X,版本:11.6,处理器:12 个
编译系统:HotSpot 64-Bit Tiered Compilers
使用内存:3MB/4096MB
垃圾收集器:G1 Young Generation,G1 Old Generation
3.2. 资源代理 MBean Server
资源代理 MBean Server 是 MBean 资源的代理,通过 MBean Server 可以让 MBean 资源用于远程管理, MBean 资源和 MBean Server 往往都是在同一个 JVM 中,但这不是必须的。
想要 MBean Server 可以管理 MBean 资源,首先要把资源注册到 MBean Server,任何符合 JMX 的 MBean 资源都可以进行注册,最后 MBean Server 会暴露一个远程通信接口对外提供服务。
3.3. JMX 远程管理
可以通过网络协议访问 JMX API,如 HTTP 协议、SNMP(网络管理协议)协议、RMI 远程调用协议等,JMX 技术默认实现了 RMI 远程调用协议。
受益于资源管理 MBean 的充分解耦,可以轻松的把资源管理功能扩展到其他协议,如通过 HTTP 在网页端进行管理。
4. JMX 的具体使用
在资源管理 MBean 部分已经演示了使用 JMX 获取 JVM 运行信息,那么如果想要自定义一个资源 MBean 呢?
下面通过一个例子,模拟一个内存资源 MBean,最后对它进行远程管理。
4.1. 编写资源管理 MBean
MBean 的编写必须遵守 JMX 的设计规范,MBean 很像一个特殊的 Java Bean,它需要一个接口和一个实现类。MBean 资源接口总是以 MBean 或者 MXBean 结尾,实现类则要以接口去掉 MBean 或 MXBean 之后的名字来命名。
编写一个内存资源管理 MBean 接口,定义如下:
package com.wdbyte.jmx;
/**
* @author https://www.wdbyte.com
*/
public interface MyMemoryMBean {
long getTotal();
void setTotal(long total);
long getUsed();
void setUsed(long used);
String doMemoryInfo();
}
然后实现这个接口:
package com.wdbyte.jmx;
/**
* @author https://www.wdbyte.com
*/
public class MyMemory implements MyMemoryMBean {
private long total;
private long used;
@Override
public long getTotal() {
return total;
}
@Override
public void setTotal(long total) {
this.total = total;
}
@Override
public long getUsed() {
return used;
}
@Override
public void setUsed(long used) {
this.used = used;
}
@Override
public String doMemoryInfo() {
return String.format("使用内存: %dMB/%dMB", used, total);
}
}
这个例子在
MyMemory.java
中只有两个long
基本类型属性,所以接口是以 MBean 结尾。如果资源实现类中的属性是自定义实体类的引用,那么接口就需要以 MXBean 结尾。
这样就完成了线程数量资源 MBean 的创建,其中 total
和 used
是资源属性,doMemoryInfo
是资源操作方法。
4.2. 注册资源到 MBean Server
通过上面的 JMX 架构图,我们知道 MBean 资源需要注册到 MBean Server 进行代理才可以暴露给外部进行调用,所以我们想要通过远程管理我们自定义的 MyMemory 资源,需要先进行资源代理。
package com.wdbyte.jmx;
import java.lang.management.ManagementFactory;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/**
* @author https://www.wdbyte.com
*/
public class MyMemoryManagement {
public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException,
InstanceAlreadyExistsException, MBeanRegistrationException, InterruptedException {
// 获取 MBean Server
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
MyMemory myMemory = new MyMemory();
myMemory.setTotal(100L);
myMemory.setUsed(20L);
// 注册
ObjectName objectName = new ObjectName("com.wdbyte.jmx:type=myMemory");
platformMBeanServer.registerMBean(myMemory, objectName);
while (true) {
// 防止进行退出
Thread.sleep(3000);
System.out.println(myMemory.doMemoryInfo());
}
}
}
启动后可以看到控制台每隔三秒打印我们自定义的内存信息。
使用内存: 20MB/100MB
使用内存: 20MB/100MB
不加任何 JVM 参数启动 Java 程序,JMX 只能在当前机器访问,如果想要通过网络在真正的远程访问,那么在启动时需要指定当前机器 ip 和开放的端口。
$ java -Dcom.sun.management.jmxremote=true \ # 开启远程访问
-Dcom.sun.management.jmxremote.port=8398 \ # 自定义 JMX 端口
-Dcom.sun.management.jmxremote.ssl=false \ # 是否使用 SSL 协议,生产环境一定要开启
-Dcom.sun.management.jmxremote.authenticate=false \ # 是否需要认证,生产环境一定要开启
-Djava.rmi.server.hostname=150.158.2.56 YourClass.java # 当前机器 ip
4.3. 远程管理 jconsole
jconsole
是 Java 自带的基于 JMX 技术的监控管理工具,如果已经配置了 JDK 环境变量,可以直接控制台通过 jconsole
命令启动。
启动 jconsole 后会列出当前机器上的 Java 进行,这里选择自己要监控的 Java 进程进行监控,连接后会提示不安全的协议,是因为 Java 程序默认启动是不会配置 HTTPS 协议的原因。
连接后可以看到多维度的 JVM 监控信息,这些信息都是通过读取 JVM 资源 MBean 信息得到的。
在下面这个页面列举了线程信息,注意最下面的线程信息,可以看到 RMI TCP
线程,这里也证明了 JMX 默认通过 RMI 协议进行远程管理。
在 MBean 页面可以浏览所有可管理的 MBean 信息,也可以看到我们自定义的 com.wdbyte.jmx
中的内存信息,甚至可以直接修改其中的 used
变量。
修改后控制台日志立即发生变化,可以看到已经修改成功。
使用内存: 20MB/100MB
使用内存: 20MB/100MB
使用内存: 20MB/100MB
使用内存: 30MB/100MB
在操作中可以调用 doMemoryInfo
方法,调用后可以看到返回值中使用内存已经由启动时的 20MB 更新为 30MB。
一如既往,当前文章中的代码示例都存放在 github.com/niumoo/JavaNotes.
当前系列:
参考:
<完>
Hello world : ) 我是阿朗,一线技术工具人,认认真真写文章,求个点赞。
文章持续更新,可以关注公众号「程序猿阿朗 」或访问未读代码博客(https://www.wdbyte.com) 」。
本文 Github.com/niumoo/JavaNotes 已经收录,有很多知识点和系列文章,欢迎Star。
Java 监控基础 - 使用 JMX 监控和管理 Java 程序的更多相关文章
- zabbix监控tomcat(使用jmx监控,但不使用系统自带模版)
一,zabbx使用jmx监控tomcat的原理分析 1.Zabbix-Server找Zabbix-Java-Gateway获取Java数据 2.Zabbix-Java-Gateway找Java程序(j ...
- 监控应用服务器使用JMX监控Tomcat (推荐)
前言:做了一个监控应用服务器的项目(支持Tocmat.WebSphere.WebLogic各版本), 过程也算是磕磕绊绊,由于网上缺少相关资料,或者深陷于知识的海洋难以寻觅到有效的资料,因而走过不少弯 ...
- 性能测试之监控--zabbix通过jmx监控tomcat
前提: 已经安装好了zabbix server 实验环境 Centos 7 Zabbix 3.0 Tomcat 7.0 JDK 1.8 安装JDK tar -zxvf jdk-8u181-linux- ...
- java线程基础巩固---如何给你的应用程序注入钩子程序
这次做一个比较有意思的实验,我们知道当一个程序如果抛异常了其程序肯定会挂掉,那有木有可能在程序异常退出时能执行一段咱们自己的代码,比如说服务器在异常退出时需要做一些额外的资源清理,像这种场景就正好是这 ...
- Docker 基础知识 - 使用卷(volume)管理应用程序数据
卷(volumes)是 Docker 容器生产和使用持久化数据的首选机制.绑定挂载(bind mounts)依赖于主机的目录结构,卷(volumes)完全由 Docker 管理.卷与绑定挂载相比有几个 ...
- 使用Collectd + InfluxDB + Grafana进行JMX监控
我们已经看到使用Collectd监控CPU /内存利用率(本文).但它没有提供所有信息来确定性能问题的瓶颈.在本文中,我们将使用Collectd Java插件来使用其JMX技术来监视和管理Java虚拟 ...
- day01<计算机基础知识&Java语言基础>
计算机基础知识(计算机概述) 计算机基础知识(软件开发和计算机语言概述) 计算机基础知识(人机交互) 计算机基础知识(键盘功能键和快捷键) 计算机基础知识(如何打开DOS控制台) 计算机基础知识(常见 ...
- Android逆向-java代码基础
作者:I春秋作家——HAI_ 0×00 前言 看这篇可以先看看之前的文章,进行一个了解.Android逆向-java代码基础(1)Android逆向-java代码基础(2) 之前看到有大佬用smali ...
- day05<Java语言基础--数组>
Java语言基础(数组概述和定义格式说明) Java语言基础(数组的初始化动态初始化) Java语言基础(Java中的内存分配以及栈和堆的区别) Java语言基础(数组的内存图解1一个数组) Java ...
随机推荐
- C++ map操作——插入、查找、遍历
c++ map 操作学习 #include <iostream> #include <map> #include <string> #include <vec ...
- Luogu P1084 疫情控制 | 二分答案 贪心
题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...
- python的分支结构
python分支结构 if结构 python的 if 选择分支结构的基础语法如下,需要注意的是判断条件后面是半角的分号,它的作用相当于Java中的小括号 if 判断条件 : 代码块 elif 判断条件 ...
- 开源项目|Go 开发的一款分布式唯一 ID 生成系统
原文连接: 开源项目|Go 开发的一款分布式唯一 ID 生成系统 今天跟大家介绍一个开源项目:id-maker,主要功能是用来在分布式环境下生成唯一 ID.上周停更了一周,也是用来开发和测试这个项目的 ...
- mybatis之参数传递的方式 | mybatis
1.单个参数(基本类/包装类+String) 这种情况MyBatis可直接使用这个参数,不需要经过任何处理. 一个参数情况下#{}中内容随便写 public Employee getEmployeeB ...
- 多层pcb线路板的制作流程
PCB制作第一步是整理并检查pcb多层线路板布局(Layout).电路板制作工厂收到PCB设计公司的CAD文件,由于每个CAD软件都有自己独特的文件格式,所以深圳PCB板厂会转化为一个统一的格式Ger ...
- vue3 学习笔记 (二)——axios 的使用有变化吗?
本篇文章主要目的就是想告诉我身边,正在学 vue3 或者 准备学 vue3 的同学,vue3中网络请求axios该如何使用,防止接触了一点点 vue3 的同学会有个疑问?生命周期.router .vu ...
- 『学了就忘』Linux软件包管理 — 44、在RPM包中提取文件
目录 1.RPM包中文件的提取 2.在RPM包中提取文件的操作 (1)cpio命令介绍 (2)提取RPM包中文件 1.RPM包中文件的提取 为什么要做这个事呢? 在操作Linux系统的时候误删除一个文 ...
- dos的基本命令
打开cmd的方式 开始+系统+命令提示符 Win键+R 输入cmd打开控制台(推荐使用) 在任意的文件夹下面,按住shift键+鼠标右键点击,在此处打开命令行窗口 资源管理器的地址栏前面加上cmd + ...
- kafka数据清理
Kafka将数据持久化到了硬盘上,允许你配置一定的策略对数据清理,清理的策略有两个,删除和压缩. 数据清理的方式 删除 log.cleanup.policy=delete启用删除策略直接删除,删除后的 ...