JVM Profiler CpuAndMemoryProfiler
开篇
CpuAndMemoryProfiler主要用来采集cpu和memory相关的信息,采集核心方法都是由ManagementFactory提供的接口:
- getClassLoadingMXBean() 返回 Java 虚拟机的类加载系统的管理 Bean。
- getCompilationMXBean() 返回 Java 虚拟机的编译系统的管理 Bean。
- getGarbageCollectorMXBeans() 返回 Java 虚拟机中的 GarbageCollectorMXBean 对象列表。
- getMemoryManagerMXBeans() 返回 Java 虚拟机中的 MemoryManagerMXBean 对象列表。
- getMemoryMXBean() 返回 Java 虚拟机的内存系统的管理 Bean。
- getMemoryPoolMXBeans() 返回 Java 虚拟机中的 MemoryPoolMXBean 对象列表。
- getOperatingSystemMXBean() 返回运行 Java 虚拟机的操作系统的管理 Bean。
- getPlatformMBeanServer() 返回平台 MBeanServer。
- getRuntimeMXBean() 返回 Java 虚拟机的运行时系统的管理 Bean。
- getThreadMXBean() 返回 Java 虚拟机的线程系统的管理 Bean。
源码分析
采集器核心对象的初始化
- 通过ManagementFactory.getPlatformMBeanServer初始化platformMBeanServer。
- 通过ObjectName.getInstance()初始化operatingSystemObjectName。
public class CpuAndMemoryProfiler extends ProcessInfoBase implements Profiler { public final static String PROFILER_NAME = "CpuAndMemory"; private static final AgentLogger logger = AgentLogger.getLogger(CpuAndMemoryProfiler.class.getName()); private static final String ATTRIBUTE_NAME_ProcessCpuLoad = "ProcessCpuLoad"; private static final int ATTRIBUTE_INDEX_ProcessCpuLoad = 0; private static final String ATTRIBUTE_NAME_SystemCpuLoad = "SystemCpuLoad"; private static final int ATTRIBUTE_INDEX_SystemCpuLoad = 1; private static final String ATTRIBUTE_NAME_ProcessCpuTime = "ProcessCpuTime"; private static final int ATTRIBUTE_INDEX_ProcessCpuTime = 2; private long intervalMillis = Constants.DEFAULT_METRIC_INTERVAL; private MBeanServer platformMBeanServer; private ObjectName operatingSystemObjectName; private MemoryMXBean memoryMXBean; private Reporter reporter; public CpuAndMemoryProfiler(Reporter reporter) { setReporter(reporter); init(); } private void init() { try { platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); operatingSystemObjectName = ObjectName.getInstance("java.lang:type=OperatingSystem"); } catch (Throwable ex) { logger.warn("Failed to get Operation System MBean", ex); } try { memoryMXBean = ManagementFactory.getMemoryMXBean(); } catch (Throwable ex) { logger.warn("Failed to get Memory MBean", ex); } }
属性采集过程
- ManagementFactory.getPlatformMBeanServer().getAttributes()获取cpu属性
- ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()获取堆使用属性。
- ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()获取非堆的使用属性。
- ManagementFactory.getGarbageCollectorMXBeans()获取内存使用属性。
- ManagementFactory.getPlatformMXBeans()回去实例对象的属性。
- 通过读取/proc/self/status文件来获取进程状态属性。
- 组装所有参数上报。
public synchronized void profile() { Double processCpuLoad = null; Double systemCpuLoad = null; Long processCpuTime = null; // 获取cpu属性 getCpuAttributes,通过platformMBeanServer对象来获取 AttributeList cpuAttributes = getCpuAttributes(); if (cpuAttributes != null && cpuAttributes.size() > 0) { Attribute att = (Attribute) cpuAttributes.get(ATTRIBUTE_INDEX_ProcessCpuLoad); processCpuLoad = (Double) att.getValue(); if (processCpuLoad == Double.NaN) { processCpuLoad = null; } att = (Attribute) cpuAttributes.get(ATTRIBUTE_INDEX_SystemCpuLoad); systemCpuLoad = (Double) att.getValue(); if (systemCpuLoad == Double.NaN) { systemCpuLoad = null; } att = (Attribute) cpuAttributes.get(ATTRIBUTE_INDEX_ProcessCpuTime); processCpuTime = (Long) att.getValue(); } // 获取memory属性,通过memoryMXBean对象来获取 Double heapMemoryTotalUsed = null; Double heapMemoryCommitted = null; Double nonHeapMemoryTotalUsed = null; Double nonHeapMemoryCommitted = null; if (memoryMXBean != null) { MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); heapMemoryTotalUsed = new Double(memoryUsage.getUsed()); heapMemoryCommitted = new Double(memoryUsage.getCommitted()); memoryUsage = memoryMXBean.getNonHeapMemoryUsage(); nonHeapMemoryTotalUsed = new Double(memoryUsage.getUsed()); nonHeapMemoryCommitted = new Double(memoryUsage.getCommitted()); } List<Map<String, Object>> gcMetrics = new ArrayList<>(); // 获取垃圾回收对象,通过ManagementFactory.getGarbageCollectorMXBeans()来实现 List<GarbageCollectorMXBean> gcMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); if (gcMXBeans != null) { for (GarbageCollectorMXBean gcMXBean : gcMXBeans) { Map<String, Object> gcMap = new HashMap<>(); gcMap.put("name", gcMXBean.getName()); gcMap.put("collectionCount", new Long(gcMXBean.getCollectionCount())); gcMap.put("collectionTime", new Long(gcMXBean.getCollectionTime())); gcMetrics.add(gcMap); } } // 获取memoryPoolsMetrics指标,通过ManagementFactory.getMemoryPoolMXBeans())来实现 List<Map<String, Object>> memoryPoolsMetrics = new ArrayList<>(); for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) { Map<String, Object> memoryPoolMap = new HashMap<>(); memoryPoolMap.put("name", pool.getName()); memoryPoolMap.put("type", pool.getType().toString()); memoryPoolMap.put("usageCommitted", pool.getUsage().getCommitted()); memoryPoolMap.put("usageMax", pool.getUsage().getMax()); memoryPoolMap.put("usageUsed", pool.getUsage().getUsed()); memoryPoolMap.put("peakUsageCommitted", pool.getPeakUsage().getCommitted()); memoryPoolMap.put("peakUsageMax", pool.getPeakUsage().getMax()); memoryPoolMap.put("peakUsageUsed", pool.getPeakUsage().getUsed()); memoryPoolsMetrics.add(memoryPoolMap); } // 获取bufferPoolsMetrics指标,通过ManagementFactory.getPlatformMXBeans()来实现 List<Map<String, Object>> bufferPoolsMetrics = new ArrayList<>(); List<BufferPoolMXBean> bufferPools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); if (bufferPools != null) { for (BufferPoolMXBean pool : bufferPools) { Map<String, Object> bufferPoolMap = new HashMap<>(); bufferPoolMap.put("name", pool.getName()); bufferPoolMap.put("count", new Long(pool.getCount())); bufferPoolMap.put("memoryUsed", new Long(pool.getMemoryUsed())); bufferPoolMap.put("totalCapacity", new Long(pool.getTotalCapacity())); bufferPoolsMetrics.add(bufferPoolMap); } } // 获取procStatus指标,通过ProcFileUtils.getProcStatus()来实现 Map<String, String> procStatus = ProcFileUtils.getProcStatus(); Long procStatusVmRSS = ProcFileUtils.getBytesValue(procStatus, "VmRSS"); Long procStatusVmHWM = ProcFileUtils.getBytesValue(procStatus, "VmHWM"); // 组装所有采集结果进行上报 Map<String, Object> map = new HashMap<String, Object>(); map.put("epochMillis", System.currentTimeMillis()); map.put("name", getProcessName()); map.put("host", getHostName()); map.put("processUuid", getProcessUuid()); map.put("appId", getAppId()); if (getTag() != null) { map.put("tag", getTag()); } if (getCluster() != null) { map.put("cluster", getCluster()); } if (getRole() != null) { map.put("role", getRole()); } map.put("processCpuLoad", processCpuLoad); map.put("systemCpuLoad", systemCpuLoad); map.put("processCpuTime", processCpuTime); map.put("heapMemoryTotalUsed", heapMemoryTotalUsed); map.put("heapMemoryCommitted", heapMemoryCommitted); map.put("nonHeapMemoryTotalUsed", nonHeapMemoryTotalUsed); map.put("nonHeapMemoryCommitted", nonHeapMemoryCommitted); map.put("gc", gcMetrics); map.put("memoryPools", memoryPoolsMetrics); map.put("bufferPools", bufferPoolsMetrics); if (procStatusVmRSS != null) { map.put("vmRSS", procStatusVmRSS); } if (procStatusVmHWM != null) { map.put("vmHWM", procStatusVmHWM); } if (reporter != null) { reporter.report(PROFILER_NAME, map); } }
cpu属性的获取过程
- platformMBeanServer.getAttributes()方法用来获取cpu的信息。
private AttributeList getCpuAttributes() { try { String[] names = new String[]{ATTRIBUTE_NAME_ProcessCpuLoad, ATTRIBUTE_NAME_SystemCpuLoad, ATTRIBUTE_NAME_ProcessCpuTime}; AttributeList list = platformMBeanServer.getAttributes(operatingSystemObjectName, names); if (list.size() != names.length) { logger.warn("Failed to get all attributes"); return new AttributeList(); } return list; } catch (Throwable ex) { logger.warn("Failed to get CPU MBean attributes", ex); return null; } } }
进程状态获取
- 通过读取/proc/self/status文件来获取进程信息。
private static final String PROC_SELF_STATUS_FILE = "/proc/self/status"; public static Map<String, String> getProcStatus() { return getProcFileAsMap(PROC_SELF_STATUS_FILE); } public static Map<String, String> getProcFileAsMap(String filePath) { try { File file = new File(filePath); if (!file.exists() || file.isDirectory() || !file.canRead()) { return Collections.emptyMap(); } Map<String, String> result = new HashMap<>(); List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); for (String line : lines) { int index = line.indexOf(VALUE_SEPARATOR); if (index <= 0 || index >= line.length() - 1) { continue; } String key = line.substring(0, index).trim(); String value = line.substring(index + 1).trim(); result.put(key, value); } return result; } catch (Throwable ex) { logger.warn("Failed to read file " + filePath, ex); return Collections.emptyMap(); } }
参考文章
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
当你完全认清程序员这个行业,你才能越走越远
程序员是一个具备长久生命力的职业 我大学刚毕业的时候,程序员还是一个年轻的职业,那个年代,我们都没见过35岁以上的程序员。很多人告诉我,程序员是吃青春饭的,你在国内见过35岁的程序员吗?我说,没有。 就是嘛,所以要尽早转行呀...... 这种话听得着实不少,事实上也真的有很多程序员早早转行了,我没转不是因为内心强大,而是我喜欢编程,尽管我也不小了,以后会怎样,35岁听起来像光年一样的距离,谁会考虑那么遥远的事情。所以我什么都没想就继续编程了。 看看周围的朋友,他们要么在某个技术领域成为行家里手,要么在做产品的同时演讲布道,有的设计出了很多人使用的软件,有的则成为了一个纯粹的管理者,经营着上千人的机构。这些人从前是程序员,现在也是。 程序员是这个时代最好的职业之一,是不是最好,不敢确认,毕竟我没离开过互联网行业。不过程序员喜欢自嘲倒是真的,甚至以互黑作为生活的乐趣,有时我们也会被别人黑到喜马拉雅山的高度,但不可否认的是,大部分程序员都是在空调房里敲敲键盘就有可能冷不丁改变了世界,并且,大部分时候,我们都让这个世界变得好了一点点。与很多职业相比,程序员的投入产出比都算高的,稍有智力门槛,也...
- 下一篇
leaflet教程
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gisdoer/article/details/82415601 leaflet简介 本教程使用leaflet进行基本的地图开发,功能介绍,代码演示。 特点: leaflet是开源的JavaScript地图库 对移动设备很友好,只有38k,却基本包含了地图开发的所有功能。 大量插件进行扩展 代码简单易上手 leaflet系列教程请进入leaflet入门教程
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7