博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JMX获取jvm参数,cpu使用率,内存,线程,类等信息,实现一个简单的web版jvisualvm
阅读量:2061 次
发布时间:2019-04-29

本文共 16726 字,大约阅读时间需要 55 分钟。

一 什么是JMX

JMX(英语:Java Management Extensions,即Java管理扩展)是平台上为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构平台、系统和,灵活的开发无缝集成的系统、网络和服务管理应用。

以上是的介绍

JMX即Java Management Extensions(Java管理扩展),是Java SE的一部分,在Java2的时候加入到Java SE平台中,但Java5才正式发布。JMX提供了一个非常简单的途径去管理应用程序的资源,这里的所说的资源包括内存资源,磁盘资源等,而且因为JMX相关技术是动态的,所以可以在应用程序运行时监控和管理资源。

想必大家都听说过 jconsole或jvisualvm,它们就是用jmx实现的。

二 MBean

具体可参阅

MBean是类似于JavaBeans组件的托管Java对象,它遵循JMX规范中阐明的设计模式。MBean可以代表设备,应用程序或任何需要管理的资源。MBean公开了一个包含以下内容的管理接口:

  • 一组可读或可写的属性,或两者兼而有之。
  • 一组可调用的操作。
  • 自我描述。

在MBean实例的整个生命周期中,管理界面都不会更改。当某些预定义事件发生时,MBeans也可以发出通知。

JMX规范定义了五种类型的MBean:

  • Standard MBeans
  • Dynamic MBeans
  • Open MBeans
  • Model MBeans
  • MXBeans

下面介绍了一种特殊的MBean类型,称为MXBeans

一个的MXBean是一种MBean的只引用一组预定义的数据类型。这样,您可以确保您的MBean可被任何客户端(包括远程客户端)使用,而无需客户端有权访问代表MBean类型的特定于模型的类。MXBean提供了一种方便的方法来将相关值捆绑在一起,而无需将客户端特别配置为处理捆绑。

以与标准MBean相同的方式,通过编写称为的Java接口SomethingMXBean和实现该接口的Java类来定义MXBean 。但是,与标准MBean不同,MXBean不需要调用Java类Something。接口中的每个方法都定义MXBean中的属性或操作。注释@MXBean也可以用于注释Java接口,而不是要求接口名称后跟MXBean后缀。

软件包中的Java 2 Platform Standard Edition(J2SE)5.0软件中存在MXBean 。

包里提供了许多MXBean的接口类,可以很方便的获取到JVM的内存、GC、线程、锁、class、甚至操作系统层面的各种信息,本文就简单的介绍 一种利用JMX对JAVA进程进行CPU、堆内存使用的监控。咱们经常使用jsconsole中的(概述/内存/线程/类/vm概要)就是通过java.lang.management中的定义的MXBean 获取到的。·

在这里插入图片描述
目前java平台主要提供了下图所示的9个MXBean, 各个MXBean的作用根据类名大概能猜出几分,具体可查API。
在这里插入图片描述
java.lang.management包中的mxbean提供了基本的功能,在sum.com.management中对某些功能有所增强,当然我们也可以根据JMX规范提供自己的MXBean。

三 获取MXBean

获取MXBean有本地调用和jmxrmi(远程调用)两种方式,通过ManagementFactory(java.lang.management.ManagementFactory)工厂类获取。

  • ManagementFactory类是用于获取Java平台的受管Bean的工厂类。 该类由静态方法组成,每个方法返回一个或多个表示Java虚拟机组件的管理接口的平台MXBeans
1 本地调用

本地调用自能获取当前程序所运行的jvm所加载的MXBean信息

//获取内存MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();//获取编译信息CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();//获取系统信息OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();//获取运行时信息RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();//获取线程信息ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();//获取类加载信息ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();//获取内存池的管理(如堆,元空间)信息List
memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();//获取gc信息List
garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans();
2 jmxrmi远程调用
//远程服务器地址final String HOSTNAME = "172.36.0.231";//远程服务器端口final int PORT = 60001;//1.构建JMX API连接器服务器的初始化地址String serviceURL = "service:jmx:rmi:///jndi/rmi://" + HOSTNAME + ":" + PORT + "/jmxrmi";JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceURL);//2.初始化客户端JMX API连接器,创建与给定地址的连接器服务器的连接。JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);//3.启动管理bean服务器连接,获取远程MBean服务器的 MBeanServerConnection对象//MBeanServerConnection 此接口表示与MBean服务器通信的方式,无论是本地还是远程。 代表本地MBean服务器的MBeanServer接口扩展了此接口。MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();//4.拿到MBeanServerConnection后就可以通过它来获取对应的MXBean//获取内存MemoryMXBean memoryMXBean = ManagementFactory.newPlatformMXBeanProxy                (mBeanServerConnection, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);//获取编译信息CompilationMXBean compilationMXBean = ManagementFactory.newPlatformMXBeanProxy                (mBeanServerConnection, ManagementFactory.COMPILATION_MXBEAN_NAME, CompilationMXBean.class);//获取系统信息OperatingSystemMXBean systemMXBean = ManagementFactory.newPlatformMXBeanProxy(    mBeanServerConnection,    ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,    com.sun.management.OperatingSystemMXBean.class);//获取运行时信息RuntimeMXBean runtimeMXBean = ManagementFactory.newPlatformMXBeanProxy(    mBeanServerConnection,    ManagementFactory.RUNTIME_MXBEAN_NAME,    RuntimeMXBean.class);//获取线程信息ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(    mBeanServerConnection,    ManagementFactory.THREAD_MXBEAN_NAME,    ThreadMXBean.class);//获取类加载信息ClassLoadingMXBean classLoading = ManagementFactory.newPlatformMXBeanProxy(    mBeanServerConnection,    ManagementFactory.CLASS_LOADING_MXBEAN_NAME,    ClassLoadingMXBean.class);//获取内存信息List
memoryPool = ManagementFactory.getPlatformMXBeans(mBeanServerConnection, MemoryPoolMXBean.class);//获取gc信息List
garbageCollectors = ManagementFactory.getPlatformMXBeans(mBeanServerConnection, GarbageCollectorMXBean.class);

四 MXBean使用

这个基本就是些api的调用,除了 获取cpu使用情况/gc垃圾回收活动情况需要少量计算,其他信息基本都可以拿到。

package com.example.demo.jmx;import java.lang.management.ClassLoadingMXBean;import java.lang.management.CompilationMXBean;import java.lang.management.GarbageCollectorMXBean;import java.lang.management.ManagementFactory;import java.lang.management.MemoryPoolMXBean;import java.lang.management.MemoryUsage;import com.sun.management.OperatingSystemMXBean;import java.lang.management.RuntimeMXBean;import java.lang.management.ThreadMXBean;import java.text.DecimalFormat;import java.text.DecimalFormatSymbols;import java.text.NumberFormat;import java.util.List;import java.util.Locale;import java.util.concurrent.TimeUnit;public class HeapMain {
private static NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH)); private static NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH)); public static void main(String[] args) throws InterruptedException {
//运行时情况 RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); //操作系统情况 com.sun.management.OperatingSystemMXBean os = ManagementFactory.getPlatformMXBean(com.sun.management.OperatingSystemMXBean.class); //线程使用情况 ThreadMXBean threads = ManagementFactory.getThreadMXBean(); //堆内存使用情况 MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); //非堆内存使用情况 MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); //类加载情况 ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean(); //内存池对象 List
pools = ManagementFactory.getMemoryPoolMXBeans(); //编译器和编译情况 CompilationMXBean cm = ManagementFactory.getCompilationMXBean(); //获取GC对象 List
gcmList = ManagementFactory.getGarbageCollectorMXBeans(); //运行时情况 System.out.printf("jvm.name (JVM名称-版本号-供应商):%s | version: %s | vendor: %s %n", runtime.getVmName(), runtime.getVmVersion(), runtime.getVmVendor()); System.out.printf("jvm.spec.name (JVM规范名称-版本号-供应商):%s | version: %s | vendor: %s %n", runtime.getSpecName(), runtime.getSpecVersion(), runtime.getSpecVendor()); System.out.printf("jvm.java.version (JVM JAVA版本):%s%n", System.getProperty("java.version")); System.out.printf("jvm.start.time (Java虚拟机的启动时间):%s%n", toDuration(runtime.getStartTime())); System.out.printf("jvm.uptime (Java虚拟机的正常运行时间):%s%n", runtime.getInputArguments()); System.out.printf("jvm.uptime (Java虚拟机的正常运行时间):%s%n", toDuration(runtime.getUptime())); System.out.printf("jvm.getInputArguments (JVM 启动参数):%s%n", runtime.getInputArguments()); System.out.printf("jvm.getSystemProperties (获取系统属性):%s%n", runtime.getSystemProperties()); //获取cpu使用情况/gc垃圾回收活动情况 Thread thread = new Thread(() -> showCpu(runtime, os, gcmList)); thread.start(); System.out.println("------------------------------------------------------------------------------------------------------"); //编译情况 System.out.printf("compilation.name(编译器名称):%s%n",cm.getName()); System.out.printf("compilation.total.time(编译器耗时):%d毫秒%n",cm.getTotalCompilationTime()); boolean isSupport=cm.isCompilationTimeMonitoringSupported(); if(isSupport){
System.out.println("支持即时编译器编译监控"); }else{
System.out.println("不支持即时编译器编译监控"); } System.out.printf("------------------------------------------------------------------------------------------------------"); //JVM 线程情况 System.out.printf("jvm.threads.total.count (总线程数(守护+非守护)):%d%n", threads.getThreadCount()); System.out.printf("jvm.threads.daemon.count (守护进程线程数):%d%n", threads.getDaemonThreadCount()); System.out.printf("jvm.threads.peak.count (峰值线程数):%d%n", threads.getPeakThreadCount()); System.out.printf("jvm.threads.total.start.count(Java虚拟机启动后创建并启动的线程总数):%d%n", threads.getTotalStartedThreadCount()); for(Long threadId : threads.getAllThreadIds()) {
System.out.printf("threadId: %d | threadName: %s%n", threadId, threads.getThreadInfo(threadId).getThreadName()); } System.out.println("------------------------------------------------------------------------------------------------------"); //获取GC信息 for (GarbageCollectorMXBean collectorMXBean : gcmList) {
System.out.printf("collectorMXBean.getCollectionCount(%s 垃圾回收器执行次数):%d%n",collectorMXBean.getName(), collectorMXBean.getCollectionCount()); System.out.printf("collectorMXBean.getCollectionTime(%s 垃圾回收器执行时间):%d%n",collectorMXBean.getName(), collectorMXBean.getCollectionTime()); } System.out.println("------------------------------------------------------------------------------------------------------"); //堆内存情况 System.out.printf("jvm.heap.init (初始化堆内存):%s %n", bytesToMB(heapMemoryUsage.getInit())); System.out.printf("jvm.heap.used (已使用堆内存):%s %n", bytesToMB(heapMemoryUsage.getUsed())); System.out.printf("jvm.heap.committed (可使用堆内存):%s %n", bytesToMB(heapMemoryUsage.getCommitted())); System.out.printf("jvm.heap.max (最大堆内存):%s %n", bytesToMB(heapMemoryUsage.getMax())); System.out.println("------------------------------------------------------------------------------------------------------"); //非堆内存使用情况 System.out.printf("jvm.noheap.init (初始化非堆内存):%s %n", bytesToMB(nonHeapMemoryUsage.getInit())); System.out.printf("jvm.noheap.used (已使用非堆内存):%s %n", bytesToMB(nonHeapMemoryUsage.getUsed())); System.out.printf("jvm.noheap.committed (可使用非堆内存):%s %n", bytesToMB(nonHeapMemoryUsage.getCommitted())); System.out.printf("jvm.noheap.max (最大非堆内存):%s %n", bytesToMB(nonHeapMemoryUsage.getMax())); System.out.println("------------------------------------------------------------------------------------------------------"); //系统概况 System.out.printf("os.name(操作系统名称-版本号):%s %s %s %n", os.getName(), "version", os.getVersion()); System.out.printf("os.arch(操作系统内核):%s%n", os.getArch()); System.out.printf("os.cores(可用的处理器数量):%s %n", os.getAvailableProcessors()); System.out.printf("os.loadAverage(系统负载平均值):%s %n", os.getSystemLoadAverage()); System.out.println("------------------------------------------------------------------------------------------------------"); //类加载情况 System.out.printf("class.current.load.count(当前加载类数量):%s %n", cl.getLoadedClassCount()); System.out.printf("class.unload.count(未加载类数量):%s %n", cl.getUnloadedClassCount()); System.out.printf("class.total.load.count(总加载类数量):%s %n", cl.getTotalLoadedClassCount()); System.out.println("------------------------------------------------------------------------------------------------------"); for(MemoryPoolMXBean pool : pools) {
final String kind = pool.getType().name(); final MemoryUsage usage = pool.getUsage(); System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".init(初始化):" + bytesToMB(usage.getInit())); System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".used(已使用): " + bytesToMB(usage.getUsed())); System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName()+ ".committed(可使用):" + bytesToMB(usage.getCommitted())); System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".max(最大):" + bytesToMB(usage.getMax())); System.out.println("------------------------------------------------------------------------------------------------------"); } thread.join(); } private static void showCpu(RuntimeMXBean runtime,OperatingSystemMXBean os,List
gcmList) {
//上一个cpu运行记录时间点 long prevUpTime = runtime.getUptime(); //当时cpu运行时间 long upTime; //上一次cpu运行总时间 long prevProcessCpuTime = os.getProcessCpuTime(); //当前cpu运行总时间 long processCpuTime; //上一次gc运行总时间 long prevProcessGcTime = getTotalGarbageCollectionTime(gcmList); //当前gc运行总时间 long processGcTime; //可用内核数量 int processorCount =os.getAvailableProcessors(); try {
TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
e.printStackTrace(); } int i =10; while (i>0){
processCpuTime = os.getProcessCpuTime(); processGcTime = getTotalGarbageCollectionTime(gcmList); upTime = runtime.getUptime(); long upTimeDiff = upTime - prevUpTime; //计算cpu使用率 long processTimeDiff = processCpuTime - prevProcessCpuTime; //processTimeDiff 取到得是纳秒数 1ms = 1000000ns double cpuDetail = processTimeDiff * 100.0 /1000000/ processorCount / upTimeDiff; //计算gccpu使用率 long processGcTimeDiff = processGcTime - prevProcessGcTime; double gcDetail = processGcTimeDiff * 100.0 /1000000/ processorCount / upTimeDiff; System.out.printf("cpu使用率:%s ,gc使用率:%s %n",cpuDetail,gcDetail); try {
TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
e.printStackTrace(); } prevProcessCpuTime = processCpuTime; prevUpTime = upTime; prevProcessGcTime =processGcTime; i--; } } /** * 垃圾回收期总耗时 */ protected static long getTotalGarbageCollectionTime(List
gcmList) {
long total = -1L; for (GarbageCollectorMXBean collectorMXBean : gcmList) {
total+=collectorMXBean.getCollectionTime(); } return total; } protected static String getKindName(String kind) {
if("NON_HEAP".equals(kind)) {
return "NON_HEAP(非堆内存)"; }else {
return "HEAP(堆内存)"; } } protected static String getPoolName(String poolName) {
switch (poolName) {
case "Code Cache": return poolName +"(代码缓存区)"; case "Metaspace": return poolName +"(元空间)"; case "Compressed Class Space": return poolName +"(类指针压缩空间)"; case "PS Eden Space": return poolName +"(伊甸园区)"; case "PS Survivor Space": return poolName +"(幸存者区)"; case "PS Old Gen": return poolName +"(老年代)"; default: return poolName; } } protected static String bytesToMB(long bytes) {
return fmtI.format((long)(bytes / 1024 / 1024)) + " MB"; } protected static String printSizeInKb(double size) {
return fmtI.format((long) (size / 1024)) + " kbytes"; } protected static String toDuration(double uptime) {
uptime /= 1000; if (uptime < 60) {
return fmtD.format(uptime) + " seconds"; } uptime /= 60; if (uptime < 60) {
long minutes = (long) uptime; String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute"); return s; } uptime /= 60; if (uptime < 24) {
long hours = (long) uptime; long minutes = (long) ((uptime - hours) * 60); String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour"); if (minutes != 0) {
s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute"); } return s; } uptime /= 24; long days = (long) uptime; long hours = (long) ((uptime - days) * 24); String s = fmtI.format(days) + (days > 1 ? " days" : " day"); if (hours != 0) {
s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour"); } return s; }}

五 自己来实现一个 jconsole或jvisualvm

掌握了api后,掌握一点前端技能,或者swing,JavaFXML可视化技能,基本就可以来自己实现一个 jconsole或jvisualvm。

下面是我用vue(近年来很火的前端框架)+echarts(前端可视化库)+springBoot实现的一个简陋的jvisualvm,感兴趣的可与去看看

在这里插入图片描述

在这里插入图片描述

参考文章

转载地址:http://mzmlf.baihongyu.com/

你可能感兴趣的文章
windows下VS2015使用MSVC编译FFmpeg库
查看>>
windows下VS使用FFmpeg被声明为已否决的解决方案
查看>>
Win7 x64环境下Python3.6安装使用提示丢失api-ms-win-crt-runtimel1-1-0.dll
查看>>
c++ Lambda函数
查看>>
c++仿函数
查看>>
C++ STL bind1st和bind2nd
查看>>
windows下Python安装requests
查看>>
目的:解决Ubuntu 使用gedit出现No protocol specified (gedit:14333):
查看>>
解决Ceph集群Mon和OSD网络变更或者ip(主要是mon)变换后,集群不能正常工作问题
查看>>
Python 格式化打印json数据(展开状态)
查看>>
Centos7 安装curl(openssl)和libxml2
查看>>
Centos7 离线安装RabbitMQ,并配置集群
查看>>
Centos7 or Other Linux RPM包查询下载
查看>>
运行springboot项目出现:Type javax.xml.bind.JAXBContext not present
查看>>
Java中多线程向mysql插入同一条数据冲突问题
查看>>
Idea Maven项目使用jar包,添加到本地库使用
查看>>
FastDFS集群架构配置搭建(转载)
查看>>
HTM+CSS实现立方体图片旋转展示效果
查看>>
FFmpeg 命令操作音视频
查看>>
问题:Opencv(3.1.0/3.4)找不到 /opencv2/gpu/gpu.hpp 问题
查看>>