Java-性能分析和监控工具深入详解
ALONG20 人气:0Java监控和管理
Java监控和管理API
Java Standard Edition(Java SE)平台提供的监控和管理技术 - JMX(Java Management Extensions) 技术。
Java SE 中包含了用于监控和管理的(java.lang.management)API,通过这些 API 可以实现应用程序的自我监控,此 API 主要提供了以下信息的访问:
- 类加载相关。
- JVM 相关,例如运行时间、系统环境变量、用户输入参数。
- 线程相关,例如线程状态,线程的统计信息、线程的堆栈等。
- 内存使用情况。
- GC 情况。
- 死锁检测。
- 操作系统信息。
Java 8的java.lang.management模块:
ClassLoadingMXBean:用于 Java 虚拟机的类加载系统的管理接口。
CompilationMXBean:用于 Java 虚拟机的编译系统的管理接口。
GarbageCollectorMXBean:用于 Java 虚拟机的垃圾回收的管理接口。
MemoryManagerMXBean:内存管理器的管理接口。
MemoryMXBeanJava :虚拟机的内存系统的管理接口。
MemoryPoolMXBean:内存池的管理接口。
OperatingSystemMXBean:用于操作系统的管理接口,Java 虚拟机在此操作系统上运行。
RuntimeMXBeanJava :虚拟机的运行时系统的管理接口。
ThreadMXBeanJava :虚拟机线程系统的管理接口。
Java虚拟机的监控
上面说到 Java SE 中已经内置了开箱即用的监控和管理功能,通过这些功能可以实现程序的自我监测,Java 默认已经实现了对 Java 虚拟机相关信息的监测。
下面通过一个简单的示例,演示如何通过监控管理 API 获取系统信息、编译器信息、内存信息以及垃圾收集器信息。
public static void main(String[] args) { showJvmInfo(); showMemoryInfo(); showSystem(); showClassLoading(); showCompilation(); showThread(); showGarbageCollector(); showMemoryManager(); showMemoryPool(); } /** * Java 虚拟机的运行时系统 */ public static void showJvmInfo() { RuntimeMXBean rtMxBean = ManagementFactory.getRuntimeMXBean(); System.out.println("Java 虚拟机的运行时系统(RuntimeMXBean):"); System.out.println("jvm vendor:" + rtMxBean.getVmVendor()); System.out.println("jvm name:" + rtMxBean.getVmName()); System.out.println("jvm version:" + rtMxBean.getVmVersion()); System.out.println("jvm bootClassPath:" + rtMxBean.getBootClassPath()); System.out.println("jvm start time:" + rtMxBean.getStartTime()); System.out.println("\n"); } /** * Java 虚拟机的内存系统 */ public static void showMemoryInfo() { MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean(); MemoryUsage heap = memoryMxBean.getHeapMemoryUsage(); System.out.println("Java 虚拟机的内存系统(MemoryMXBean):"); System.out.println("Heap " + heap.toString()); System.out.println( "Heap" + " init:" + heap.getInit() + byte2Mb(heap.getInit()) + " used:" + byte2Mb(heap.getUsed()) + " committed:" + byte2Mb(heap.getCommitted()) + " max:" + byte2Mb(heap.getMax())); System.out.println("\n"); } private static String byte2Mb(long source) { return "(" + source / 1024 / 1024 + "mb)"; } /** * Java 虚拟机在其上运行的操作系统 */ public static void showSystem() { OperatingSystemMXBean operatingSystemMxBean = ManagementFactory.getOperatingSystemMXBean(); System.out.println("Java 虚拟机在其上运行的操作系统(OperatingSystemMXBean):"); System.out.println("Architecture(操作系统架构): " + operatingSystemMxBean.getArch()); System.out.println("Processors(Java虚拟机可用的处理器数): " + operatingSystemMxBean.getAvailableProcessors()); System.out.println("System name(操作系统名称): " + operatingSystemMxBean.getName()); System.out.println("System version(操作系统版本): " + operatingSystemMxBean.getVersion()); System.out.println("Last minute load(最后一分钟的系统负载平均值): " + operatingSystemMxBean.getSystemLoadAverage()); System.out.println("\n"); } /** * Java 虚拟机的类加载系统 */ public static void showClassLoading() { ClassLoadingMXBean classLoadingMxBean = ManagementFactory.getClassLoadingMXBean(); System.out.println("Java 虚拟机的类加载系统(ClassLoadingMXBean):"); System.out.println("TotalLoadedClassCount(加载的类总数): " + classLoadingMxBean.getTotalLoadedClassCount()); System.out.println("LoadedClassCount(当前加载的类的数量)" + classLoadingMxBean.getLoadedClassCount()); System.out.println("UnloadedClassCount(卸载类的总数):" + classLoadingMxBean.getUnloadedClassCount()); System.out.println("\n"); } /** * Java 虚拟机的编译系统 */ public static void showCompilation() { CompilationMXBean compilationMxBean = ManagementFactory.getCompilationMXBean(); System.out.println("Java 虚拟机的编译系统(CompilationMXBean):"); System.out.println("TotalCompilationTime(编译时间(毫秒)):" + compilationMxBean.getTotalCompilationTime()); System.out.println("name(JIT编译器的名称):" + compilationMxBean.getName()); System.out.println("\n"); } /** * Java 虚拟机的线程系统 */ public static void showThread() { ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean(); System.out.println("Java 虚拟机的线程系统(ThreadMXBean):"); System.out.println("ThreadCount(当前活动线程数)" + threadMxBean.getThreadCount()); System.out.println("PeakThreadCount(峰值实时线程计数)" + threadMxBean.getPeakThreadCount()); System.out.println("TotalStartedThreadCount(启动的线程总数)" + threadMxBean.getTotalStartedThreadCount()); System.out.println("DaemonThreadCount(当前活动后台进程线程数)" + threadMxBean.getDaemonThreadCount()); System.out.println("isSynchronizerUsageSupported(虚拟机是否支持监视可下载同步器的使用情况)" + threadMxBean.isSynchronizerUsageSupported()); System.out.println("AllThreadIds(所有活动线程ID):" + JSON.toJSONString(threadMxBean.getAllThreadIds())); System.out.println("CurrentThreadUserTime(当前线程在用户模式下执行的CPU时间(以纳秒为单位))" + threadMxBean.getCurrentThreadUserTime()); for (ThreadInfo threadInfo : threadMxBean.getThreadInfo(threadMxBean.getAllThreadIds(), 1)) { System.out.print(threadInfo.getThreadId() + threadInfo.toString()); } System.out.println("\n"); } /** * Java 虚拟机中的垃圾回收器。 */ public static void showGarbageCollector() { List<GarbageCollectorMXBean> collectorMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); System.out.println("Java 虚拟机中的垃圾回收器(GarbageCollectorMXBean):"); for (GarbageCollectorMXBean collectorMxBean : collectorMxBeans) { System.out.println("name(垃圾收集器名称):" + collectorMxBean.getName()); System.out.println("--CollectionCount:" + collectorMxBean.getCollectionCount()); System.out.println("--CollectionTime" + collectorMxBean.getCollectionTime()); System.out.println("\n"); } System.out.println("\n"); } /** * Java 虚拟机中的内存管理器 */ public static void showMemoryManager() { List<MemoryManagerMXBean> memoryManagerMxBeans = ManagementFactory.getMemoryManagerMXBeans(); System.out.println("Java 虚拟机中的内存管理器(MemoryManagerMXBean):"); for (MemoryManagerMXBean managerMxBean : memoryManagerMxBeans) { System.out.println("name(内存管理器名称):" + managerMxBean.getName()); System.out.println("--MemoryPoolNames:" + String.join(",", managerMxBean.getMemoryPoolNames())); System.out.println("\n"); } System.out.println("\n"); } /** * Java 虚拟机中的内存池 */ public static void showMemoryPool() { List<MemoryPoolMXBean> memoryPoolMxBeans = ManagementFactory.getMemoryPoolMXBeans(); System.out.println("Java 虚拟机中的内存池(MemoryPoolMXBean):"); for (MemoryPoolMXBean memoryPoolMxBean : memoryPoolMxBeans) { System.out.println("name:" + memoryPoolMxBean.getName()); System.out.println("--CollectionUsage:" + memoryPoolMxBean.getCollectionUsage()); System.out.println("--type:" + memoryPoolMxBean.getType()); System.out.println("\n"); } System.out.println("\n"); } }
输出:
Java 虚拟机的运行时系统(RuntimeMXBean): jvm vendor:Oracle Corporation jvm name:Java HotSpot(TM) 64-Bit Server VM jvm version:25.221-b11 jvm bootClassPath:F:\opt\Java\jdk8\jre\lib\resources.jar;F:\opt\Java\jdk8\jre\lib\rt.jar;F:\opt\Java\jdk8\jre\lib\sunrsasign.jar;F:\opt\Java\jdk8\jre\lib\jsse.jar;F:\opt\Java\jdk8\jre\lib\jce.jar;F:\opt\Java\jdk8\jre\lib\charsets.jar;F:\opt\Java\jdk8\jre\lib\jfr.jar;F:\opt\Java\jdk8\jre\classes jvm start time:1673181328952 Java 虚拟机的内存系统(MemoryMXBean): Heap init = 268435456(262144K) used = 4028824(3934K) committed = 257425408(251392K) max = 3791650816(3702784K) Heap init:268435456(256mb) used:(3mb) committed:(245mb) max:(3616mb) Java 虚拟机在其上运行的操作系统(OperatingSystemMXBean): Architecture(操作系统架构): amd64 Processors(Java虚拟机可用的处理器数): 8 System name(操作系统名称): Windows 10 System version(操作系统版本): 10.0 Last minute load(最后一分钟的系统负载平均值): -1.0 Java 虚拟机的类加载系统(ClassLoadingMXBean): TotalLoadedClassCount(加载的类总数): 507 LoadedClassCount(当前加载的类的数量)507 UnloadedClassCount(卸载类的总数):0 Java 虚拟机的编译系统(CompilationMXBean): TotalCompilationTime(编译时间(毫秒)):8 name(JIT编译器的名称):HotSpot 64-Bit Tiered Compilers Java 虚拟机的线程系统(ThreadMXBean): ThreadCount(当前活动线程数)5 PeakThreadCount(峰值实时线程计数)5 TotalStartedThreadCount(启动的线程总数)5 DaemonThreadCount(当前活动后台进程线程数)4 isSynchronizerUsageSupported(虚拟机是否支持监视可下载同步器的使用情况)true AllThreadIds(所有活动线程ID):[5,4,3,2,1] CurrentThreadUserTime(当前线程在用户模式下执行的CPU时间(以纳秒为单位))234375000 5"Attach Listener" Id=5 RUNNABLE 4"Signal Dispatcher" Id=4 RUNNABLE 3"Finalizer" Id=3 WAITING on java.lang.ref.ReferenceQueue$Lock@17c68925 at java.lang.Object.wait(Native Method) - waiting on java.lang.ref.ReferenceQueue$Lock@17c68925 2"Reference Handler" Id=2 WAITING on java.lang.ref.Reference$Lock@7e0ea639 at java.lang.Object.wait(Native Method) - waiting on java.lang.ref.Reference$Lock@7e0ea639 1"main" Id=1 RUNNABLE at sun.management.ThreadImpl.getThreadInfo1(Native Method) Java 虚拟机中的垃圾回收器(GarbageCollectorMXBean): name(垃圾收集器名称):PS Scavenge --CollectionCount:0 --CollectionTime0 name(垃圾收集器名称):PS MarkSweep --CollectionCount:0 --CollectionTime0 Java 虚拟机中的内存管理器(MemoryManagerMXBean): name(内存管理器名称):CodeCacheManager --MemoryPoolNames:Code Cache name(内存管理器名称):Metaspace Manager --MemoryPoolNames:Metaspace,Compressed Class Space name(内存管理器名称):PS Scavenge --MemoryPoolNames:PS Eden Space,PS Survivor Space name(内存管理器名称):PS MarkSweep --MemoryPoolNames:PS Eden Space,PS Survivor Space,PS Old Gen Java 虚拟机中的内存池(MemoryPoolMXBean): name:Code Cache --CollectionUsage:null --type:Non-heap memory name:Metaspace --CollectionUsage:null --type:Non-heap memory name:Compressed Class Space --CollectionUsage:null --type:Non-heap memory name:PS Eden Space --CollectionUsage:init = 67108864(65536K) used = 0(0K) committed = 0(0K) max = 1399848960(1367040K) --type:Heap memory name:PS Survivor Space --CollectionUsage:init = 11010048(10752K) used = 0(0K) committed = 0(0K) max = 11010048(10752K) --type:Heap memory name:PS Old Gen --CollectionUsage:init = 179306496(175104K) used = 0(0K) committed = 0(0K) max = 2843738112(2777088K) --type:Heap memory Disconnected from the target VM, address: '127.0.0.1:12687', transport: 'socket' Process finished with exit code 0
Java监控和管理工具
JMX 技术中提到 JMX 不仅提供了监控和管理的 API ,还提供了用于网络远程管理的服务,可以使用 JMX 相关监控管理工具,通过网络远程连接到正在运行 Java 虚拟机,监控其运行状态。
JMC(Java Mission Control)
Java Mission Control使您能够监视和管理Java应用程序,而不会引入通常与这些类型的工具相关联的性能开销。
它使用为Java虚拟机(JVM)的常规自适应动态优化收集的数据。
除了最小化性能开销之外,这种方法还消除了观察器效应的问题,当监视工具改变系统的执行特性时会发生这种问题。
Java Mission Control由客户端应用程序(JMC客户端)和在其上运行的许多插件组成:
- JVM Browser显示正在运行的Java应用程序及其JVM。每个JVM实例都称为JVM连接。
- JMX Console连接到正在运行的JVM,实时收集和显示其特征,并允许您通过Managed Beans(MBean)更改某些运行时属性。您还可以创建触发某些事件的规则(例如,如果应用程序的CPU使用率达到90%,则发送电子邮件)。
- Java Flight Recorder(JFR)收集并保存详细的性能特征,以进行历史分析和分析。它可以用作独立的性能监视和分析工具,但是当用作JMC客户端的插件时,它会在逻辑分组的表,图表和拨号中显示诊断信息。它使您可以选择专注于问题所需的时间范围和详细程度。
- Java Mission Control插件使用Java Management Extensions(JMX)代理连接到JVM。
启动JMC
双击JAvA_HOME\bin\jmc.exe 文件启动JMC
连接远程程序添加配置:
-Dcom.sun.management.jmxremote.port=7001 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=your ip
JMC功能介绍
MBean浏览器中查看类属性信息:
内存栏目查看GC、各个内存区域使用情况:
线程状态、死锁、堆栈信息:
诊断命令,查询vm信息等:
JFR(Java Flight Recorder)
黑匣子是用于记录飞机飞行和性能参数的仪器。在飞机出问题后,用于定位问题原因。JFR 就是 Java 的黑匣子。
JFR 是 Java Flight Record (Java飞行记录) 的缩写,是 JVM 内置的基于事件的JDK监控记录框架。
这个起名就是参考了黑匣子对于飞机的作用,将Java进程比喻成飞机飞行。
顾名思义,这个记录主要用于问题定位和持续监控。
如果是利用默认配置启动这个记录,性能非常高效,对于业务影响很小,因为这个框架本来就是用来长期在线上部署的框架。
这个记录可以输出成二进制文件,用户可以指定最大记录时间,或者最大记录大小,供用户在需要的时候输出成文件进行事后分析。
JFR在Java应用运行时收集对应发生的事件,主要有三种类型的事件提供给JFR收集:
- 即时事件:一旦事件发生会立即进行数据记录
- 持续事件:如果持续时间超过指定阈值则进行数据记录
- 简单事件:用于记录应用所在系统的活跃指标(例如CPU,内存等)
开启JFR记录
通过启动参数配置并且启用 JFR,也可以通过启动参数在 JVM 进程启动的时候就启动 JFR,或者是利用 jcmd 工具,动态启用或者关闭 JFR。
JDK 8中的-XX:+FlightRecorder
java -XX:StartFlightRecording=disk=true,dumponexit=true,filename=recording.jfr,maxsize=1024m,maxage=1d,settings=profile,path-to-gc-roots=true test.Main
JConsole
Jconsole (Java Monitoring and Management Console),一种基于JMX的可视化监视、管理工具。
JConsole 基本包括以下基本功能:概述、内存、线程、类、VM概要、MBean。
概述
内存
线程
可以看到线程列表、线程状态、线程名称、线程堆栈等信息。
类
可以看到 已加装当前类、已加载类总数、已卸载类总数。
VM
MXBean
JVisualVM
VisualVM(All-in-One Java Troubleshooting Tool);功能最强大的运行监视和故障处理程序。
功能描述:
- 显示虚拟机进程以及进程的配置、环境信息(jps、jinfo)。
- 监视应用程序的CPU、GC、堆、方法区(1.7及以前),元空间(JDK1.8及以后)以及线程的信息(jstat、jstack)。
- dump以及分析堆转储快照(jmap、jhat)。
- 方法级的程序运行性能分析,找出被调用最多、运行时间最长的方法。
- 离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照。
Java Management Extensions(JMX)
加载全部内容