使用JMX来获取CPU利用率和GC 所占用的CPU利用率

来源:互联网 发布:硅藻土吸水地垫 知乎 编辑:程序博客网 时间:2024/05/29 15:31

这篇博客会介绍如何通过JMX 来获取JAVA 进程占用的CPU利用率和GC所占用的CPU利用率


在使用JVisualVM的时候,发现它可以查看当前JAVA 进程占用的CPU利用率和GC 所占用的CPU利用率,很奇怪它是如何计算的或者怎么获取的.
本文会根据JVisualVM的源码来描述JVisualVM是如何计算的.

获取源码

GITHUB 地址: https://github.com/visualvm/visualvm.src
百度云:http://pan.baidu.com/s/1boHI4HL

目标数据

运行jvisualvm, 目标是获取图中的CPU Usage 和 GC activity.
target

HOW TO

将源码导入Intellij后,可以全局搜索GC activity,然后可以查看到:
在Bundle.properties 中:

LBL_Gc_Usage=GC activity

然后查看这个property的使用地方:

com.sun.tools.visualvm.application.views.monitor.ApplicationMonitorView.CpuViewSupport...        private static final String CPU = NbBundle.getMessage(ApplicationMonitorView.class, "LBL_Cpu"); // NOI18N        private static final String CPU_USAGE = NbBundle.getMessage(ApplicationMonitorView.class, "LBL_Cpu_Usage"); // NOI18N        private static final String GC_USAGE = NbBundle.getMessage(ApplicationMonitorView.class, "LBL_Gc_Usage"); // NOI18N...private void initModels(ApplicationMonitorModel model) {            liveModel = model.isLive();            processorsCount = model.getProcessorsCount();            cpuMonitoringSupported = model.isCpuMonitoringSupported();            gcMonitoringSupported = model.isGcMonitoringSupported();            SimpleXYChartDescriptor chartDescriptor =                    //下面的这个后面会讲到                    SimpleXYChartDescriptor.percent(false, 0.1d, model.getChartCache());            chartDescriptor.addLineItems(CPU_USAGE, GC_USAGE);            chartDescriptor.setDetailsItems(new String[] { CPU_USAGE, GC_USAGE });            chartSupport = ChartFactory.createSimpleXYChart(chartDescriptor);//这里就应该就是界面显示的注册了.   那么注册后是如何使用的???            model.registerCpuChartSupport(chartSupport);            chartSupport.setZoomingEnabled(!liveModel);        }

主要的计算逻辑集中在其refresh方法中:

public void refresh(ApplicationMonitorModel model) {     //如果监控CPU            if (cpuMonitoringSupported || gcMonitoringSupported) {     //获取当前的UPTIME                long upTime = model.getUpTime() * 1000000;                //获取上次的UPTIME                long prevUpTime = model.getPrevUpTime() * 1000000;                boolean tracksProcessCpuTime = cpuMonitoringSupported &&                                               model.getPrevProcessCpuTime() != -1;                                               //获取当前的CPU时间                long processCpuTime = tracksProcessCpuTime ?                    model.getProcessCpuTime() / processorsCount : -1;                    //获取上次的CPU时间                long prevProcessCpuTime = tracksProcessCpuTime ?                    model.getPrevProcessCpuTime() / processorsCount : -1;                boolean tracksProcessGcTime  = gcMonitoringSupported &&                                               model.getPrevProcessGcTime() != -1;                                               //获取当前的GC占用时间                long processGcTime  = tracksProcessGcTime  ?                    model.getProcessGcTime() * 1000000 / processorsCount : -1;                    //获取上次的GC占用时间                long prevProcessGcTime  = tracksProcessGcTime  ?                    model.getPrevProcessGcTime() * 1000000 / processorsCount : -1;                if (prevUpTime != -1 && (tracksProcessCpuTime || tracksProcessGcTime)) {                    long upTimeDiff = upTime - prevUpTime;                    //分别计算CPU使用率和GC的CPU使用率.                    long cpuUsage = -1;                    long gcUsage = -1;                    String cpuDetail = UNKNOWN;                    String gcDetail = UNKNOWN;                    if (tracksProcessCpuTime) {                        long processTimeDiff = processCpuTime - prevProcessCpuTime;                        cpuUsage = upTimeDiff > 0 ? Math.min((long)(1000 * (float)processTimeDiff /                                                             (float)upTimeDiff), 1000) : 0;                        cpuDetail = cpuUsage == -1 ? UNKNOWN : chartSupport.formatPercent(cpuUsage);                    }                    if (tracksProcessGcTime) {                        long processGcTimeDiff = processGcTime - prevProcessGcTime;                        gcUsage = upTimeDiff > 0 ? Math.min((long)(1000 * (float)processGcTimeDiff /                                                            (float)upTimeDiff), 1000) : 0;                        if (cpuUsage != -1 && cpuUsage < gcUsage) gcUsage = cpuUsage;                        gcDetail = gcUsage == -1 ? UNKNOWN : chartSupport.formatPercent(gcUsage);                    }                    if (liveModel)                        //设置视图的值 达到刷新的目的                        //可以看到这个值和界面上显示是相差0.1倍的 原因是前面的那个chartDescriptor 有个0.1d的显示倍率.                        chartSupport.addValues(model.getTimestamp(), new long[] { Math.max(cpuUsage, 0), Math.max(gcUsage, 0) });                    chartSupport.updateDetails(new String[] { cpuDetail, gcDetail });                }            }        }

可以看到逻辑主要是ApplicationMonitorModel model对象的相关方法中,下面介绍这些时间是如何获取的:
ApplicationMonitorModel的方法:
private void updateValues(final long time, final MonitoredData data)实现了简单的值更新.主要就是prevXXX = xxx

private void updateValues(final long time, final MonitoredData data) {        timestamp = time;        if (data != null) {            prevUpTime = uptime;            uptime = data.getUpTime();            ....            其他类似

具体实现就在:MonitoredData中.
getUpTime:

getUpTime获取upTime:RuntimeMXBean.getUpTime获取CPU时间:/*JMXPath _processCpuTimeJMXPath = new JMXPath("java.lang:type=OperatingSystem:ProcessCpuTime");获取这个JMXPath的值就可以*/if (jmxSupport.hasProcessCPUTimeAttribute()) {            processCpuTime = jmxSupport.getProcessCPUTime(); // 与        }获取GC时间: 累加的GC时间 //   gcList = ManagementFactory.getGarbageCollectorMXBeans();                if (gcList != null && !gcList.isEmpty()) {            for (GarbageCollectorMXBean gcBean : gcList) {                collectionTime+=gcBean.getCollectionTime();            }        }
0 0
原创粉丝点击