2026/5/14 3:05:42
网站建设
项目流程
做网站加推广多少钱,免费网站建设哪家好,水果商城的设计与实现,医院网站建设公司价格JVM 性能监控和故障处理工具
在线上处理问题的时候#xff0c;知识#xff0c;经验是关键基础#xff0c;数据是依据#xff0c;工具是知识处理数据的手段#xff0c;这里说的数据包括但不限于运行日志、异常堆栈、GC日志、线程快照#xff08;threaddump/javacore 文件…JVM 性能监控和故障处理工具在线上处理问题的时候知识经验是关键基础数据是依据工具是知识处理数据的手段这里说的数据包括但不限于运行日志、异常堆栈、GC日志、线程快照threaddump/javacore 文件、堆转存快照heapdump/hprof 文件等。在本文中工具主要是指 JDK 自带的工具都位于 JDK 的 bin 目录下基础故障处理工具jps进程监控工具该命令很像 UNIX 的 ps 命令列出当前用户正在运行的虚拟机进程并显示虚拟机执行主类Main Classmain() 函数所在的类名称以及这些进程的本地虚拟机唯一 IDLVMIDLocal Virtual Machine Identifier。功能虽单一但使用频率超级高。jps 命令格式jps [options] [hostid]jps 工具的主要选项-q只输出 LVMID不输出类名称、Jar 名称和传入 main 方法的参数-l输出 main 类或 Jar 的 全限定名称-m输出传入 main 方法的参数-v输出虚拟机进程启动时传入的 JVM 参数jstat统计信息监控工具jstatJVM Statistics Monitoring Tool 是用于识别虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、jit 编译等运行时数据。jstat 命令格式jstat -option [-t] [-hlines] vmid [interval [count]]option参数选项-t可以在打印的列加上 timestamp 列用于显示系统运行的时间-h可以在周期性数据的时候可以在指定输出多少行以后输出一次表头vmid进程IDlines表头与表头的间隔行数interval执行每次的间隔时间单位为毫秒count用于指定输出记录的 次数缺省则会一直打印option 值的选项-class显示类加载 ClassLoad 的相关信息-compiler:显示 JIT 编译的相关信息-gc显示和 gc相关的堆信息-gccapacity显示各个代的容量以及使用情况-gcmetacapacity显示元空间 metaspace 的大小-gcnew显示新生代信息-gcnewcapacity: 显示新生代大小和使用情况-gcold显示老年代垃圾收集状况-gcoldcapacity显示老年代的大小-gcutil显示垃圾回收信息-gccause显示垃圾回收的相关信息同 -gcutil同时显示最后一次或当前正在发生的垃圾回收的原因-printcompilation输出 JIT 编译的方法信息如上表示每 5 秒输出一次 gc 信息且输出 3 次其中S0S1表示新生代两个 Survivor 区E代表的是新生代的 Eden区C的意思是容量U表示已经使用的意思O表示的老年代M表示方法区。F和Y则表示 fullGC 和 minorGC。GCT表示GC Time。jinfo配置信息工具jinfoConfiguration Info for Java的作用是实时地查看和调整虚拟机各项参数使用 jps 命令的 -v 参数可以查看虚拟机启动时显式指定的参数列表。但如果想知道未被显式指定的参数的系统默认值除了去找资料外就只能使用 jinfo 的 -flag 选项进行查询。no option输出全部的参数和系统属性-flag name输出对应名称的参数-flag [|-]name开启或者关闭对应名称的参数我们可以通过 jinfo 实时的修改虚拟机的参数但是不是任何命令都可以修改可以修改的参数我们先来执行这个命令java -XX:PrintFlagsFinal -version会列出当前机器支持的所有参数那么用 jinfo 可以修改的参数是什么呢只有最后一列显示manageable的这一列才能进行修改。仔细查看发现可修改的参数其实并不多jvm 的运行内存一旦在运行时确定下来那么就无法修改。但是无法一些错误信息没有记录或者是处于关闭状态还是可以修改的。jinfo 命令格式jinfo [-options] pid查看某一进程是否开启了GC日志信息的详细打印jinfo -flag PrintGCDetails pid查看堆内存大小jinfo -flag MaxHeapSize pidjmp内存映像工具jampMemory Map for Java命令用于生成堆转储快照一般称为 heapdump 或 dump 文件。如果不使用jmap 命令要想获取 Java 堆转储快照还有一些比较“暴力”的手段譬如-XX : HeapDumpOnOutOfMemoryError参数可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件通过-XX : HeapDumpOnCtrlBreak参数则可以使用[Ctrl][Break]键让虚拟机生成 dump 文件又或者在 Linux 系统下通过Kill-3命令发送进程退出信号“吓唬”一下虚拟机也能拿到 dump 文件。jmap 的作用并不仅仅是为了获取 dump 文件他还可以查询 finalize 执行队列、Java 堆和方法区的详细信息如空间使用率、当前用的是哪种收集器等。和 jinfo 命令一样jmap 有不少功能在 Windows 平台下都是受限的除了生成 dump 文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外其余选项都只能在 Linux/Solaris下使用。jmap 命令格式jmap [-options] vmidoption 值的选项dump生成Java堆转储快照。格式为-dump:[live, ]formatb, filefilename其中 live 子参数说明是否只 dump 出存活的对象-finalizerinfo显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象。只在 Linux/Solaris 平台下有效-heap显示 Java 堆详细信息如使用哪种回收器、参数配置、分代状况等。只在 Linux/Solaris 平台下有效-histo显示堆中对象统计信息包括类、实例数量、合计容量-permstat以 ClassLoader 为统计口径显示永久代内存状态。只在 Linux/Solaris 平台下有效-F当虚拟机进程对 -dump 选项没有响应时可使用这个选项强制生成 dump 快照。只在 Linux/Solaris 平台下有效jhat堆转储快照分析工具jhatJVM Heap Analysis Tool命令与 jmap 搭配使用来分析 jmap 生成的堆转储快照。jhat 内置了一个微型的 HTTP/HTML 服务器生成 dump 文件的分析结果后可以在浏览器中查看。不过实事求是地说在实际工作中除非手上真的没有别的工具可用否则一般都不会去直接使用 jhat 命令来分析 dump 文件主要原因有两个一般不会在部署应用程序的服务器上直接分析 dump 文件即使可以这样做也会尽量将 dump 文件复制到其他机器。分析工作是一个耗时而且消耗硬件资源的过程既然都要在其他机器进行就没有必要受到命令行工具的限制了jhat 的分析功能相对来说比较简陋VisualVM以及专业用于分析 dump 文件的 Eclipse Memory Analyzer、IBM HeapAnalyzer 等工具都能实现比 jhat 更强大更专业的分析功能。jstack堆栈跟踪工具jstack 用于生成虚拟机当前时刻的线程快照。线程快照是当前虚拟机内每一条线程正在执行的方法堆栈的集合生成线程快照的主要目的是定位线程出现长时间停顿的原因如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过 jstack 来查看各个线程的调用堆栈就可以知道没有响应的线程到底在后台做什么事情或者等待什么资源。jstack 命令格式jstack [-options] vmidoption 值的选项-F当正常输出请求不被响应时强制输出线程堆栈-l输出锁信息-m如果调用到本地方法的话可以显示 C/C 堆栈JDK5 之后java.lang.Thread类的getAllStackTraces()方法可以获取虚拟机中所有线程的StackTraceElement 对象可以查看堆栈信息。for (Map.EntryThread, StackTraceElement[] stackTrace : Thread.getAllStackTraces().entrySet()) { Thread thread (Thread) stackTrace.getKey(); StackTraceElement[] stack (StackTraceElement[]) stackTrace.getValue(); if (thread.equals(Thread.currentThread())) { continue; } System.out.println(Thread name is : thread.getName()); for (StackTraceElement stackTraceElement : stack) { System.out.println(\t stackTraceElement); } }统计线程数jstack -l 28367 | grep java.lang.Thread.State | wc -ljstack 检测 CPU 过高toptop -H -p pid查看cpu占用高线程的 tidprintf %x\n tid将线程 ID 转换为 16进制格式的 nidjstack pid|grep nid -A 100定位cpu占用线程可视化故障处理工具JDK 中除了附带大量的命令行工具外还提供了几个功能集成度更高的可视化工具用户可以使用这些可视化工具以更加便捷的方式进行进程故障诊断和调试工作。这类工具主要包括 JConsole、JHSDB、VisualVM 和 JMC 四个。Jconsole从Java 5开始 引入了 JConsole。JConsole 是一个内置 Java 性能分析器可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole或者它更高端的 “近亲” VisualVM 来监控 Java 应用程序性能和跟踪 Java 中的代码。VisualVMVisualVM 是一款免费的集成了多个 JDK 命令行工具的可视化工具它能为您提供强大的分析能力对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析同时它还支持在 MBeans 上进行浏览和操作。本文主要介绍如何使用 VisualVM 进行性能分析及调优。恰当的使用虚拟机故障处理、分析工具可以提升我们分析数据、定位并解决问题的效率但我们也要知道工具永远都是知识技能的一层包装没有什么工具是秘密武器。OOM 问题排查的一些常用工具接下来我们来看下如何排查造成 OOM 的原因内存泄漏是最常见的造成 OOM 的一种原因所以接下来我们以来看看怎么使用工具来排查这种问题,使用到的工具主要有两大类1、使用 matEclipse Memory Analyzer 来分析 dump堆转储快照 文件主要步骤如下运行 Java 时添加 「-XX:HeapDumpOnOutOfMemoryError」 参数来导出内存溢出时的堆信息生成 hrof 文件, 添加 「-XX:HeapDumpPath」可以指定 hrof 文件的生成路径,如果不指定则 hrof 文件生成在与字节码文件相同的目录下使用 MATEclipse Memory Analyzer来分析 hrof 文件查出内存泄漏的原因接下来我们就来看看如何用以上的工具查看如下内存泄漏案例/** * VM Args:-Xmx10m */ import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { ListString list new ArrayListString(); while (true) { list.add(OutOfMemoryError soon); } } }为了让以上程序快速产生 OOM, 我把堆大小设置成了 10M, 这样执行 「java -Xmx10m -XX:HeapDumpOnOutOfMemoryError Main」后很快就发生了 OOM此时我们就拿到了 hrof 文件下载 MAT 工具打开 hrof,进行分析打开之后选择 「Leak Suspects Report」进行分析可以看到发生 OOM 的线程的堆栈信息明确定位到是哪一行造成的img如图示可以看到 Main.java 文件的第 12 行导致了这次的 OOM2、使用 jvisualvm 来分析用第一种方式必须等 OOM 后才能 dump 出 hprof 文件但如果我们想在运行中观察堆的使用情况以便查出可能的内存泄漏代码就无能为力了这时我们可以借助jvisualvm这款工具, jvisualvm 的功能强大除了可以实时监控堆内存的使用情况还可以跟踪垃圾回收运行中 dump 中堆内存使用情况、cpu分析线程分析等是查找分析问题的利器更骚的是它不光能分析本地的 Java 程序还可以分析线上的 Java 程序运行情况, 本身这款工具也是随 JDK 发布的是官方力推的一款运行监视故障处理的神器。我们来看看如何用 jvisualvm 来分析上文所述的存在内存泄漏的如下代码import java.util.Map; import java.util.HashMap; public class KeylessEntry { static class Key { Integer id; Key(Integer id) { this.id id; } Override public int hashCode() { return id.hashCode(); } } public static void main(String[] args) { MapKey,String m new HashMapKey,String(); while(true) { for(int i0;i10000;i) { if(!m.containsKey(new Key(i))) { m.put(new Key(i), Number: i); } } } } }打开 jvisualvm 终端输入 jvisualvm 执行即可打开后将堆大小设置为 500M执行命令java Xms500m -Xmx500m KeylessEntry此时可以观察到左边出现了对应的应用 KeylessEntry,双击点击 openimg打开之后可以看到展示了 CPU堆内存使用加载类及线程的情况img注意看堆Heap的使用情况一直在上涨img此时我们再点击 「Heap Dump」img过一会儿即可看到内存中对象的使用情况img可以看到相关的 TreeNode 有 291w 个远超正常情况下的 10000 个说明 HashMap 一直在增长自此我们可以定位出问题代码所在3、使用 jps jmap 来获取 dump 文件jps 可以列出正在运行的虚拟机进程并显示执行虚拟机主类及这些进程的本地虚拟机唯一 ID如图示img拿到进程的 pid 后我们就可以用 jmap 来 dump 出堆转储文件了执行命令如下jmap -dump:formatb,fileheapdump.phrof pid拿到 dump 文件后我们就可以用 MAT 工具来分析了。 但这个命令在生产上一定要慎用因为JVM 会将整个 heap 的信息 dump 写入到一个文件heap 比较大的话会导致这个过程比较耗时并且执行过程中为了保证 dump 的信息是可靠的会暂停应用jstat 与可视化 APM 工具构建jstat 是用于监视虚拟机各种运行状态信息的命令行工具可以显示本地或者远程虚拟机进程中的类加载内存垃圾收集JIT 编译等运行数据jstat 支持定时查询相应的指标如下jstat -gc 2764 250 22定时针对 2764 进程输出堆的垃圾收集情况的统计可以显示 gc 的信息查看gc的次数及时间,利用这些指标把它们可视化对分析问题会有很大的帮助,如图示下图就是我司根据 jstat 做的一部分 gc 的可视化报表能快速定位发生问题的问题点如果大家需要做 APM 可视化工具建议配合使用 jstat 来完成。