一、背景
工作中我们需要对自己负责的系统的运行状态进行监控,这个通常会使用公司内部的监控系统。我本来是没想太多的,但有次无意中了解到公司对于GC次数时间的监控居然是自己写程序解析JVM的gc日志,这让我有点大吃一惊,我虽然知道JVM对外提供了接口获取各种信息,但当时又一下子想不起来叫什么名字,怎么用,于是决定总结一下这块东西,写个Demo记下来便于以后使用是查看。
二、解决方案
其实要获取JVM运行时的各项指标非常简单,只需要调用JVM提供的接口进行获取就好,核心类名叫做ManagementFactory,下面一一介绍一下。
1.JVM启动参数
System.out.println("===============程序运行参数==================");RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();//JVM启动参数System.out.println(runtimeMXBean.getInputArguments());//系统属性System.out.println(runtimeMXBean.getSystemProperties());//JVM名字 System.out.println(runtimeMXBean.getVmName());
2.线程状态
System.out.println("===============线程状态=======================");ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();//获取当前JVM内的线程数量,该指标非常重要。//之前遇到过用为没有对该指标进行监控而导致问题无法及时定位的情况。System.out.println(threadMXBean.getThreadCount());System.out.println(threadMXBean.getCurrentThreadCpuTime());System.out.println(threadMXBean.getCurrentThreadUserTime());
3.类加载情况
System.out.println("===============类加载状态============================");ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();//获取当前JVM加载的类数量System.out.println(classLoadingMXBean.getLoadedClassCount());//获取JVM总加载的类数量System.out.println(classLoadingMXBean.getTotalLoadedClassCount());//获取JVM卸载的类数量 System.out.println(classLoadingMXBean.getUnloadedClassCount());
4.系统状态
System.out.println("================系统状态======================");OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();//获取服务器的CPU个数System.out.println(operatingSystemMXBean.getAvailableProcessors());//获取服务器的平均负载。这个指标非常重要,它可以有效的说明当前机器的性能是否正常,如果load过高,说明CPU无法及时处理任务。System.out.println(operatingSystemMXBean.getSystemLoadAverage());
5.总内存内存使用状态
System.out.println("================内存状态===========================");MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();//获取堆内存使用情况,包括初始大小,最大大小,已使用大小等,单位字节System.out.println(memoryMXBean.getHeapMemoryUsage().toString());//获取堆外内存使用情况。System.out.println(memoryMXBean.getNonHeapMemoryUsage().toString());
6.各个内存区使用状态
System.out.println("================堆内存状态======================");//这里会返回老年代,新生代等内存区的使用情况,按需自取就好ListmemoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();memoryPoolMXBeans.forEach((pool) -> { System.out.println(pool.getName()); System.out.println(pool.getUsage());});输出结果:================堆内存状态======================Code Cacheinit = 2555904(2496K) used = 1497216(1462K) committed = 2555904(2496K) max = 251658240(245760K) Metaspace init = 0(0K) used = 4513312(4407K) committed = 5111808(4992K) max = -1(-1K) Compressed Class Space init = 0(0K) used = 513592(501K) committed = 655360(640K) max = 1073741824(1048576K) PS Eden Space init = 8388608(8192K) used = 4191808(4093K) committed = 8388608(8192K) max = 8388608(8192K) PS Survivor Space init = 1048576(1024K) used = 0(0K) committed = 1048576(1024K) max = 1048576(1024K) PS Old Gen init = 10485760(10240K) used = 0(0K) committed = 10485760(10240K) max = 20971520(20480K)
6.GC状态
JVM启动参数:-server -Xmx30m -Xms20m -Xmn10m -XX:+UseParNewGC -XX:+UseConcMarkSweepGCSystem.out.println("===============GC状态==========================");ListgarbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();garbageCollectorMXBeans.forEach(collector -> { System.out.println(collector.getName()); System.out.println(collector.getCollectionCount()); System.out.println(collector.getCollectionTime());});输出结果:===============GC状态==========================ParNew12 24 ConcurrentMarkSweep 24 225
三、总结
有了这些基础数据以后就可以监控我们的系统运行状态,比如说起一个daemon线程,每秒中统计一下数据,有问题就报警。分布式系统的话可以定时上报系统的运行状态然后再进行汇总监控。