利用JMX统计远程JAVA进程的CPU和Memory
2017-01-19 14:12
375 查看
http://songzi0206.iteye.com/blog/1541636
********************
从JAVA 5开始,JDK提供了一些JVM检测的API,这就是有名的java.lang.management 包,包里提供了许多MXBean的接口类,可以很方便的获取到JVM的内存、GC、线程、锁、class、甚至操作系统层面的各种信息,本文就简单的介绍一种利用JMX对JAVA进程进行CPU、堆内存使用的监控。可能有人会觉得没必要这样做,因为用jconsole之类的工具都能做到,而且会比本文的例子更详细。但是有些时候将console不一定能监控到作为系统服务的java进程,我最近就不得不自己编码去获取远程java进程的监控数据。希望能起到抛砖引玉的作用吧。
首先,简要介绍下JMX(Java Management Extensions),即JAVA管理扩展,用来监视和管理JVM以及其运行的操作系统。目前java平台主要提供了下图所示的9个MXBean, 各个MXBean的作用根据类名大概能猜出几分,具体可查API。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/e9bfdad50b52465b600b4b594f5effeb.jpg)
java.lang.management包中的mxbean提供了基本的功能,在sum.com.management中对某些功能有所增强,当然我们也可以根据JMX规范提供自己的MXBean。
下面我主要使用java.lang.management.MemoryMXBean和sun.com.management.OperatingSystemMXBean分别对远程JAVA进行内存和cpu的监控。根据需求5秒钟读取一次数据,内存主要是已使用的Heap
Memory,CPU主要就是使用率了。
在使用OperatingSystemMXBean以及MemoryMXBean之前,首先必须得到JMXConnector并创建MBeanServerConnnection,有了这个connection我们就可以利用ManagementFactory创建需要的MXBean了,类依赖图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/8436725b46fe9f10506e90f08328c3a0.jpg)
示例代码:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
/*
* host: 远程机器的ip地址
* port: 远程java进程运行的jmxremote端口
*/
JMXServiceURL serviceURL = new JMXServiceURL( host,port );
JMXConnector conn = JMXConnectorFactory.connect(serviceURL);
MBeanServerConnection mbs=conn.getMBeanServerConnection();
//获取远程memorymxbean
MemoryMXBean memBean=ManagementFactory.newPlatformMXBeanProxy
(mbs,ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
//获取远程opretingsystemmxbean
com.sun.management.OperatingSystemMXBean opMXbean =
ManagementFactory.newPlatformMXBeanProxy(mbs,
ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
然后,采集memory的数据就比较简单了,直接调用API获取:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
/** Collect data every 5 seconds */
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
logger.error("InterruptedException occurred while MemoryCollector sleeping...");
}
MemoryUsage heap = memBean
etHeapMemoryUsage();
MemoryUsage nonHeap = memBean
etNonHeapMemoryUsage();
long heapSizeUsed = heap.getUsed();//堆使用的大小
long nonHeapSizeUsed = nonHeap.getUsed();
long heapCommitedSize = heap.getCommitted();
long nonHeapCommitedSize = nonHeap.getCommitted();
采集CPU利用率需要自己计算一下,因为API只提供了获取cpu的使用时间,我得在两次系统时间间隔内获取两次CPU的使用时间,得到在该时间间隔内cpu使用的时间,相除即得到CPU的使用率,当然误差肯定存在。
计算cpu使用率代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
Long start = System.currentTimeMillis();
long startT = opMXbean.getProcessCpuTime();
/** Collect data every 5 seconds */
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
logger.error("InterruptedException occurred while MemoryCollector sleeping...");
}
Long end = System.currentTimeMillis();
long endT = opMXbean.getProcessCpuTime();
//end - start 即为当前采集的时间单元,单位ms
//endT - startT 为当前时间单元内cpu使用的时间,单位为ns
//所以:double ratio = (entT-startT)/1000000.0/(end-start)/opMXbean.getAvailableProcessors()
核心代码就是这些了,当然,具体使用的话应该用单独的线程分别取cpu、memory数据,读取的数据需要写文件或者画图,监控时间长的话还要定时的将这些数据刷到磁盘文件或数据库中,等,这些都是题外话了。这边我写到excel中,然后在excel中图形展示,远程监控的程序不方便展示,仅仅来监控一段模拟cpu正弦曲线的程序
,来看看我监控到的数据(图形)是否和预期一致,并与jconsole采到的有何差异:
被测程序,模拟cpu正弦曲线代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
public class SinCpu {
public static final double TIME = 1000;
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws InterruptedException {
new Thread(new SinTask()).start();
}
static class SinTask implements Runnable{
@Override
public void run() {
double x = 0;
double y = 0;
while (true) {
y = (Math.sin(x) + 1) * TIME / 2;
doSomeSimpleWork(y);
x += 0.1;
try {
Thread.sleep((long) (TIME - y));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void doSomeSimpleWork(double y) {
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < y) {
}
}
}
}
监控结果基本和预期一样,CPU数据图呈现预期的正弦曲线:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/1244278c6650b71da1d7a2647538bedc.jpg)
上图中,第一个图是从jconsole监控图中截过来的,而下图是我利用opMXBean计算获得,两个图基本吻合,数据基本波动在0-25%是因为我测试机器是四核的cpu,两个图像之间有位移是因为,我手动打开jconsole没有我程序监控来的快,所以大概图像平移下基本吻合。
内存的测试应该比CPU还要准一些,这里就不贴了。Note: 如果监控的程序线程数量很大,cpu会有较明显误差,而且采的频率不够高的话可能有些点漏采。
最后:被测程序必须开放JMXREMOTE端口,具体使用参数:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=[开放的端口]
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
********************
从JAVA 5开始,JDK提供了一些JVM检测的API,这就是有名的java.lang.management 包,包里提供了许多MXBean的接口类,可以很方便的获取到JVM的内存、GC、线程、锁、class、甚至操作系统层面的各种信息,本文就简单的介绍一种利用JMX对JAVA进程进行CPU、堆内存使用的监控。可能有人会觉得没必要这样做,因为用jconsole之类的工具都能做到,而且会比本文的例子更详细。但是有些时候将console不一定能监控到作为系统服务的java进程,我最近就不得不自己编码去获取远程java进程的监控数据。希望能起到抛砖引玉的作用吧。
首先,简要介绍下JMX(Java Management Extensions),即JAVA管理扩展,用来监视和管理JVM以及其运行的操作系统。目前java平台主要提供了下图所示的9个MXBean, 各个MXBean的作用根据类名大概能猜出几分,具体可查API。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/e9bfdad50b52465b600b4b594f5effeb.jpg)
java.lang.management包中的mxbean提供了基本的功能,在sum.com.management中对某些功能有所增强,当然我们也可以根据JMX规范提供自己的MXBean。
下面我主要使用java.lang.management.MemoryMXBean和sun.com.management.OperatingSystemMXBean分别对远程JAVA进行内存和cpu的监控。根据需求5秒钟读取一次数据,内存主要是已使用的Heap
Memory,CPU主要就是使用率了。
在使用OperatingSystemMXBean以及MemoryMXBean之前,首先必须得到JMXConnector并创建MBeanServerConnnection,有了这个connection我们就可以利用ManagementFactory创建需要的MXBean了,类依赖图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/8436725b46fe9f10506e90f08328c3a0.jpg)
示例代码:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
/*
* host: 远程机器的ip地址
* port: 远程java进程运行的jmxremote端口
*/
JMXServiceURL serviceURL = new JMXServiceURL( host,port );
JMXConnector conn = JMXConnectorFactory.connect(serviceURL);
MBeanServerConnection mbs=conn.getMBeanServerConnection();
//获取远程memorymxbean
MemoryMXBean memBean=ManagementFactory.newPlatformMXBeanProxy
(mbs,ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
//获取远程opretingsystemmxbean
com.sun.management.OperatingSystemMXBean opMXbean =
ManagementFactory.newPlatformMXBeanProxy(mbs,
ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
然后,采集memory的数据就比较简单了,直接调用API获取:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
/** Collect data every 5 seconds */
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
logger.error("InterruptedException occurred while MemoryCollector sleeping...");
}
MemoryUsage heap = memBean
etHeapMemoryUsage();
MemoryUsage nonHeap = memBean
etNonHeapMemoryUsage();
long heapSizeUsed = heap.getUsed();//堆使用的大小
long nonHeapSizeUsed = nonHeap.getUsed();
long heapCommitedSize = heap.getCommitted();
long nonHeapCommitedSize = nonHeap.getCommitted();
采集CPU利用率需要自己计算一下,因为API只提供了获取cpu的使用时间,我得在两次系统时间间隔内获取两次CPU的使用时间,得到在该时间间隔内cpu使用的时间,相除即得到CPU的使用率,当然误差肯定存在。
计算cpu使用率代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
Long start = System.currentTimeMillis();
long startT = opMXbean.getProcessCpuTime();
/** Collect data every 5 seconds */
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
logger.error("InterruptedException occurred while MemoryCollector sleeping...");
}
Long end = System.currentTimeMillis();
long endT = opMXbean.getProcessCpuTime();
//end - start 即为当前采集的时间单元,单位ms
//endT - startT 为当前时间单元内cpu使用的时间,单位为ns
//所以:double ratio = (entT-startT)/1000000.0/(end-start)/opMXbean.getAvailableProcessors()
核心代码就是这些了,当然,具体使用的话应该用单独的线程分别取cpu、memory数据,读取的数据需要写文件或者画图,监控时间长的话还要定时的将这些数据刷到磁盘文件或数据库中,等,这些都是题外话了。这边我写到excel中,然后在excel中图形展示,远程监控的程序不方便展示,仅仅来监控一段模拟cpu正弦曲线的程序
,来看看我监控到的数据(图形)是否和预期一致,并与jconsole采到的有何差异:
被测程序,模拟cpu正弦曲线代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/c89a3fb8c96032f8212c9bdbbddbdddd.png)
public class SinCpu {
public static final double TIME = 1000;
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws InterruptedException {
new Thread(new SinTask()).start();
}
static class SinTask implements Runnable{
@Override
public void run() {
double x = 0;
double y = 0;
while (true) {
y = (Math.sin(x) + 1) * TIME / 2;
doSomeSimpleWork(y);
x += 0.1;
try {
Thread.sleep((long) (TIME - y));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void doSomeSimpleWork(double y) {
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < y) {
}
}
}
}
监控结果基本和预期一样,CPU数据图呈现预期的正弦曲线:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201511/1244278c6650b71da1d7a2647538bedc.jpg)
上图中,第一个图是从jconsole监控图中截过来的,而下图是我利用opMXBean计算获得,两个图基本吻合,数据基本波动在0-25%是因为我测试机器是四核的cpu,两个图像之间有位移是因为,我手动打开jconsole没有我程序监控来的快,所以大概图像平移下基本吻合。
内存的测试应该比CPU还要准一些,这里就不贴了。Note: 如果监控的程序线程数量很大,cpu会有较明显误差,而且采的频率不够高的话可能有些点漏采。
最后:被测程序必须开放JMXREMOTE端口,具体使用参数:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=[开放的端口]
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
相关文章推荐
- 利用JMX统计远程JAVA进程的CPU和Memory
- 利用JMX统计远程JAVA进程的CPU和Memory
- 利用JMX统计远程JAVA进程的CPU和Memory---jVM managerment API
- 利用JMX统计远程JAVA进程的CPU和Memory
- 利用VisualVm和JMX远程监控Java进程
- 利用JAVA获取远程文件及断点续传
- JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯
- 利用java实现一个简单的远程监控程序
- 利用远程线程将代码注入到目标进程中执行
- JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯
- java 利用SMB读取远程文件
- Java获取系统信息(cpu,内存,硬盘,进程等)的相关方法
- Wily EM Server进程异常终止,日志记录java.lang.OutOfMemoryError
- JAVA 进程异常高的 CPU 占用率
- 一起谈.NET技术,JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯
- 利用java实现一个简单的远程监控程序
- Java获取系统信息(cpu,内存,硬盘,进程等)的相关方法
- 利用Java.lang.Process和ProcessBuilder创建本地应用程序进程
- 利用JMX来监控大部分java应用
- 利用JAVA获取远程文件及使用断点续传,供学习者使用