首页 文章 精选 留言 我的

精选列表

搜索[jvm],共6415篇文章
优秀的个人博客,低调大师

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(); } } 参考文章 ManagementFactory api

优秀的个人博客,低调大师

JVM Profiler StacktraceCollectorProfiler

开篇 StacktraceCollectorProfiler主要用来采集线程的调用栈,原理是通过ManagementFactory.getThreadMXBean()返回的ThreadMXBean对象来实现。 源码分析 public void profile() { // 获取此刻所有线程的dump信息 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); if (threadInfos == null) { return; } // 遍历线程信息并处理每个线程 for (ThreadInfo threadInfo : threadInfos) { String threadName = threadInfo.getThreadName(); if (threadName == null) { threadName = ""; } if (!ignoreThreadNamePrefix.isEmpty() && threadName.startsWith(ignoreThreadNamePrefix)) { continue; } // 获取线程的调用栈 StackTraceElement[] stackTraceElements = threadInfo.getStackTrace(); // 创建调用栈对象 Stacktrace stacktrace = new Stacktrace(); stacktrace.setThreadName(threadName); stacktrace.setThreadState(String.valueOf(threadInfo.getThreadState())); // 创建保存调用栈的list int totalLength = 0; List<ClassAndMethod> stack = new ArrayList<>(stackTraceElements.length); // 按照倒序保存调用链,最底层的放在最前面,把最根本的原因发在前面 for (int i = stackTraceElements.length - 1; i >= 0; i--) { StackTraceElement stackTraceElement = stackTraceElements[i]; String className = String.valueOf(stackTraceElement.getClassName()); String methodName = String.valueOf(stackTraceElement.getMethodName()); stack.add(new ClassAndMethod(className, methodName)); totalLength += className.length() + methodName.length(); // 如果长度超出限制,那么就截断 if (totalLength >= Constants.MAX_STRING_LENGTH) { stack.add(new ClassAndMethod("_stack_", "_trimmed_")); break; } } // 反转调用链,把最底层的放在最前面。 ClassAndMethod[] classAndMethodArray = new ClassAndMethod[stack.size()]; for (int i = 0; i < stack.size(); i++) { classAndMethodArray[classAndMethodArray.length - 1 - i] = stack.get(i); } stacktrace.setStack(classAndMethodArray); buffer.appendValue(stacktrace); } } 采集结果 调用链的反向序列为: java.lang.Thread.sleep com.uber.profiling.examples.HelloWorldApplication.privateSleepMethod com.uber.profiling.examples.HelloWorldApplication.main { "stacktrace": ["java.lang.Thread.sleep", "com.uber.profiling.examples.HelloWorldApplication.privateSleepMethod", "com.uber.profiling.examples.HelloWorldApplication.main"], "endEpoch": 1536072801080, "appId": null, "host": "xiaozhideMacBook-Pro.local", "name": "2203@xiaozhideMacBook-Pro.local", "processUuid": "1e580f6e-0493-4e5b-bee2-a61c5f7b097d", "threadState": "TIMED_WAITING", "count": 24, "tag": "mytag", "startEpoch": 1536072796084, "threadName": "main" }

优秀的个人博客,低调大师

Java - JVM 内存管理

1. 查找失效对象 1.1 引用计数法 可以为每一个对象添加一个引用计数器,用于存储当前对象被几处引用。 引用计数法简单高效,但无法解决循环引用问题,如A引用B,B又引用A,且这两个对象不再被其它对象引用,那么在使用引用计数法的情况下,这两个对象的引用数均为1,且无法减至0。 1.2 可达性分析算法 可以通过一系列成为“GC Roots”的对象作为起始点,并从这些节点向下搜索,当一个对象到GC Roots不可达,则证明该对象不可用。 图1-1 GC Roots对象包括下面几种: o 虚拟机栈中引用的对象。 o 方法区中类静态属性引用的对象。 o 方法区中常量引用的对象。 o 本地方法栈中引用的对象。 一个对象要真正被清理,至少需要两次标记过程。 1.3 回收方法区 方法区垃圾回收的效率与性价比都远低于堆内存的回收。 主要回收两部分:废弃常量和无用的类。 2. 垃圾收集算法 2.1 标记-清除算法 图2-1 标记清除算法的标记阶段与清除阶段效率都不高,且会产生大量内存碎片。 2.2 复制算法 图2-2 将内存平分为两块,每次只使用其中一块。 当一块内存快用完时,可将存活的对象复制到另一块上面,然后将刚才使用的内存一次性清理掉。 该算法简单高效,且不会产生内存碎片,但由于有一半空闲内存,所以内存使用率不高。 HotSpot中,新生代内存结构为 1 * Eden + 2 * Survivor,每次只使用Eden区和其中一块Survivor区,当发生回收时,会将Eden与在用的Survivor中的存活对象复制到另一块Survivor区中。 根据HotSpot的内存结构,可见只有10%的内存(其中一块Survivor)被浪费,但此时有另一个问题,即实际情况下我们不能保证每次回收的存活对象都仅占内存的10%以下,所以当Survivor也不够用时,就需要依赖其它内存(老年代)做分配担保。 2.3 标记-整理算法 在对象存活率高的情况下,复制算法需要进行较多的赋值操作,效率会变低,同时备用空间也是对内存的一种浪费。 对于老年代,可能存在所有对象都存活的情况,所以直接使用复制算法是不合适的,所以出现了标记-整理算法。 图2-3 首先,标记。(这里标记的可能是所有存活对象,而非被回收对象,因为接下来需要移动存活对象,而不是清理回收对象) 然后,将存活对象向某一端移动,如图2-3,存活对象都会向上移动,其过程可能是所有存活对象依次在一端逐个覆盖。 最终,直接清理掉端边界以外的内存。 参考文献: [1]周志明.深入理解Java虚拟机[M].北京:机械工业出版社,2018.61-72

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册