虚拟机监控JMX 和系统管理

检测虚拟机当前的状态总是 Java 开放人员所关心的,也正是因为如此,出现了大量的 profiler 工具来检测当前的虚拟机状态。从 Java SE 5 之后,在 JDK 中,我们有了一些 Java 的虚拟机检测 API,即 java.lang.management包。Management 包里面包括了许多 MXBean 的接口类和 LockInfo、MemoryUsage、MonitorInfo 和 ThreadInfo 等类。从名字可以看出,该包提供了虚拟机内存分配、垃圾收集(GC)情况、操作系统层、线程调度和共享锁,甚至编译情况的检测机制。这样一来,Java 的开发人员就可以很简单地为自己做一些轻量级的系统检测,来确定当前程序的各种状态,以便随时调整。

要获得这些信息,我们首先通过 java.lang.management.ManagementFactory这个工厂类来获得一系列的 MXBean。包括:

  • ClassLoadingMXBean

    ClassLoadMXBean 包括一些类的装载信息,比如有多少类已经装载 / 卸载(unloaded),虚拟机类装载的 verbose 选项(即命令行中的 Java – verbose:class 选项)是否打开,还可以帮助用户打开 / 关闭该选项。

  • CompilationMXBean

    CompilationMXBean 帮助用户了解当前的编译器和编译情况,该 mxbean 提供的信息不多。

  • GarbageCollectorMXBean

    相对于开放人员对 GC 的关注程度来说,该 mxbean 提供的信息十分有限,仅仅提供了 GC 的次数和 GC 花费总时间的近似值。但是这个包中还提供了三个的内存管理检测类:MemoryManagerMXBean,MemoryMXBean 和 MemoryPoolMXBean。

    • MemoryManagerMXBean

      这个类相对简单,提供了内存管理类和内存池(memory pool)的名字信息。

    • MemoryMXBean

      这个类提供了整个虚拟机中内存的使用情况,包括 Java 堆(heap)和非 Java 堆所占用的内存,提供当前等待 finalize 的对象数量,它甚至可以做 gc(实际上是调用 System.gc)。

    • MemoryPoolMXBean

      该信息提供了大量的信息。在 JVM 中,可能有几个内存池,因此有对应的内存池信息,因此,在工厂类中,getMemoryPoolMXBean() 得到是一个 MemoryPoolMXBean 的 list。每一个 MemoryPoolMXBean 都包含了该内存池的详细信息,如是否可用、当前已使用内存 / 最大使用内存值、以及设置最大内存值等等。

  • OperatingSystemMXBean

    该类提供的是操作系统的简单信息,如构架名称、当前 CPU 数、最近系统负载等。

  • RuntimeMXBean

    运行时信息包括当前虚拟机的名称、提供商、版本号,以及 classpath、bootclasspath 和系统参数等等。

  • ThreadMXBean

    在 Java 这个多线程的系统中,对线程的监控是相当重要的。ThreadMXBean 就是起到这个作用。ThreadMXBean 可以提供的信息包括各个线程的各种状态,CPU 占用情况,以及整个系统中的线程状况。从 ThreadMXBean 可以得到某一个线程的 ThreadInfo 对象。这个对象中则包含了这个线程的所有信息。

java.lang.management 和虚拟机的关系

我们知道,management 和底层虚拟机的关系是非常紧密的。其实,有一些的是直接依靠虚拟机提供的公开 API 实现的,比如 JVMTI;而另外一些则不然,很大一块都是由虚拟机底层提供某些不公开的 API / Native Code 提供的。这样的设计方式,保证了 management 包可以提供足够的信息,并且使这些信息的提供又有足够的效率;也使 management 包和底层的联系非常紧密。

package com.easyway.space.commons.systems;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryManagerMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.lang.management.MonitorInfo;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

/**
 * 系统监控工具
 * management 和底层虚拟机的关系是非常紧密的。其实,有一些的是直接依靠虚拟机提供的公
 * 开 API 实现的,比如 JVMTI;而另外一些则不然,很大一块都是由虚拟机底层提供某些不公开
 * 的 API / Native Code 提供的。这样的设计方式,保证了 management 包可以提供足够的信
 * 息,并且使这些信息的提供又有足够的效率;也使 management 包和底层的联系非常紧密。
 * @author longgangbai
 * 
 */
public class SystemUtils {

	/**
	 *ClassLoadingMXBean ClassLoadMXBean 包括一些类的装载信息,
	 * 比如有多少类已经装载 / 卸载(unloaded),
	 * 虚拟机类装载的 verbose 选项(即命令行中的 Java – verbose:class 选项)是否打开,
	 * 还可以帮助用户打开 / 关闭该选项。
	 */
	public static void getVMClassInformation(){
		
		ClassLoadingMXBean classLoadMXBean=ManagementFactory.getClassLoadingMXBean();
		
		int loadClazzCount=classLoadMXBean.getLoadedClassCount();
		System.out.println("加载类的数量:"+loadClazzCount);
		
		long hasloadClazzCount=classLoadMXBean.getTotalLoadedClassCount();
		System.out.println("已经加载类的数量:"+hasloadClazzCount);
		long hasUnloadClazzCount=classLoadMXBean.getUnloadedClassCount();
		System.out.println("尚未加载类的数量:"+hasUnloadClazzCount);
		boolean isVerbose=classLoadMXBean.isVerbose();
		System.out.println("是否开始加载类信息:"+isVerbose);
		//CompilationMXBean 帮助用户了解当前的编译器和编译情况,该 mxbean 提供的信息不多。
		CompilationMXBean compilationMXBean=ManagementFactory.getCompilationMXBean();
		String jitName=compilationMXBean.getName();
		System.out.println("即时编译的名称:"+jitName);
		long totalCompileTime=compilationMXBean.getTotalCompilationTime();
		System.out.println("总的编译时间:"+totalCompileTime+"/s");
		boolean isSupport=compilationMXBean.isCompilationTimeMonitoringSupported();
		if(isSupport){
			System.out.println("支持即时编译器编译监控");
		}else{
			System.out.println("不支持即时编译器编译监控");
		}
		List<GarbageCollectorMXBean> gcMXBeanList=ManagementFactory.getGarbageCollectorMXBeans();
		//相对于开放人员对 GC 的关注程度来说,该 mxbean 提供的信息十分有限,仅仅提供了 GC 的次数和 GC 花费总时间的近似值。
		for (GarbageCollectorMXBean gcMXBean : gcMXBeanList) {
			//内存池名称
			String[] poolNames=gcMXBean.getMemoryPoolNames();
			for (String poolName : poolNames) {
				System.out.println("poolNames="+poolName);
			}
		} 
		//提供了内存管理类和内存池(memory pool)的名字信息。
		List<MemoryManagerMXBean> memoryMgrMXBeanList=ManagementFactory.getMemoryManagerMXBeans();
		//内存管理器的信息
		for (MemoryManagerMXBean memoryManagerMXBean : memoryMgrMXBeanList) {
			String[] poolNames=memoryManagerMXBean.getMemoryPoolNames();
			for (String poolName : poolNames) {
				System.out.println("poolNames="+poolName);
			}
		}
		//内存信息
		MemoryMXBean memoryMXBean=ManagementFactory.getMemoryMXBean();
		//java堆得使用情况信息
		MemoryUsage heapMemoryUsage=memoryMXBean.getHeapMemoryUsage();
		long usaged=heapMemoryUsage.getUsed();
		System.out.println("java 内存堆使用内存:"+usaged);
		long maxUsage=heapMemoryUsage.getMax();
		System.out.println("java 内存堆最大使用内存:"+maxUsage);
		long initUsage=heapMemoryUsage.getInit();
		System.out.println("java 内存堆初始化时占用内存:"+initUsage);
		List<MemoryPoolMXBean> memoryPoolMXBeanList=ManagementFactory.getMemoryPoolMXBeans();
		//该信息提供了大量的信息。在 JVM 中,可能有几个内存池,因此有对应的内存池信息,因此,在工厂类中
		//,getMemoryPoolMXBean() 得到是一个 MemoryPoolMXBean 的 list。每一个 MemoryPoolMXBean 都包含
		//了该内存池的详细信息,如是否可用、当前已使用内存 / 最大使用内存值、以及设置最大内存值等等。
		for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeanList) {
			//内存池的名称
			String poolName=memoryPoolMXBean.getName();
			//内存管理器的名称
			String[] memoryMgrNames=memoryPoolMXBean.getMemoryManagerNames();
			for (String mgrName : memoryMgrNames) {
				System.out.println("内存管理器的名称:"+mgrName);
			}
		    //java JVM最近内存的使用情况
			MemoryUsage memoryUsage=memoryPoolMXBean.getCollectionUsage();
			System.out.println("内存池的收集器内存使用率:"+memoryUsage.getUsed()/memoryUsage.getMax()+"%");
			memoryPoolMXBean.getCollectionUsageThreshold();
			
			memoryPoolMXBean.getCollectionUsageThresholdCount();
			MemoryType  memoryType=memoryPoolMXBean.getType();
			System.out.println("内存的信息:"+memoryType.name());
			MemoryUsage memoryUage=memoryPoolMXBean.getUsage();
			System.out.println("内存池的内存使用率:"+memoryUage.getUsed()/memoryUage.getMax()+"%");
			memoryPoolMXBean.getUsageThreshold();
			System.out.println();
			memoryPoolMXBean.getUsageThresholdCount();
			System.out.println();
		}
		//该类提供的是操作系统的简单信息,如构架名称、当前 CPU 数、最近系统负载等。
		OperatingSystemMXBean operateSystemMBean=ManagementFactory.getOperatingSystemMXBean();
		
		String operateName=operateSystemMBean.getName();
		System.out.println("操作系统的名称:"+operateName);
		
		int processListCount=operateSystemMBean.getAvailableProcessors();
		System.out.println("操作系统的进程数:"+processListCount);
		
		String osArchName=operateSystemMBean.getArch();//System.getProperty("os.arch");
		System.out.println("操作系统的架构:"+osArchName);
		
		double loadAverage=operateSystemMBean.getSystemLoadAverage();
		System.out.println("操作系统的负载均衡信息:"+loadAverage);
		
		String versionName=operateSystemMBean.getVersion();//System.getProperty("os.version");
		System.out.println("操作系统的版本号码:"+versionName);
		//运行时信息包括当前虚拟机的名称、提供商、版本号,以及 classpath、bootclasspath 和系统参数等等。
		RuntimeMXBean runtimeMXBean=ManagementFactory.getRuntimeMXBean();
		String vmName=runtimeMXBean.getVmName();
		System.out.println("虚拟机的名称:"+vmName);
		
		String vmVersion=runtimeMXBean.getVmVersion();
		System.out.println("虚拟机的版本:"+vmVersion);
		
		Map<String, String> sysMaps=runtimeMXBean.getSystemProperties();
		Set<Entry<String,String>> keyLists=sysMaps.entrySet();
		for (Entry<String, String> entry : keyLists) {
			System.out.println(entry.getKey()+":"+entry.getValue());
		}
		String vmVendor=runtimeMXBean.getVmVendor();
		System.out.println("系统的供应商的名称:"+vmVendor);
		
		//类加载器的路径
		String clazzPath=runtimeMXBean.getClassPath();//System.getProperty("java.class.path")}
		System.out.println("操作系统的类加载器的名称:"+clazzPath);
		
		List<String> argsList=runtimeMXBean.getInputArguments();
		System.out.println("操作系统的参数信息");
		for (String args : argsList) {
			System.out.println("  "+args);
		}
		
		String libPath=runtimeMXBean.getLibraryPath();// System.getProperty("java.library.path")
		System.out.println("java 的类库路径:"+libPath );
		
		String specVersion=runtimeMXBean.getManagementSpecVersion();
		System.out.println("实施运行Java虚拟机管理接口规范 的版本"+specVersion);
		
		String specName=runtimeMXBean.getSpecName();
		System.out.println("规范的名称:"+specName);
		
		String specVender=runtimeMXBean.getSpecVendor();
		System.out.println("规范管理接口供应商 :"+specVender);
		
		long startTime=runtimeMXBean.getStartTime();
		System.out.println("java 虚拟机的开始启动的时间:"+startTime);
		

		runtimeMXBean.getSpecVersion();
		System.out.println("规范接口版本::"+operateName);
		
		
		String bottClassPath =runtimeMXBean.getBootClassPath();
		System.out.println("操作系统的bootstrap 的classloader:"+bottClassPath);
		
		//在 Java 这个多线程的系统中,对线程的监控是相当重要的。ThreadMXBean 就是起到这个作用。
		//ThreadMXBean 可以提供的信息包括各个线程的各种状态,CPU 占用情况,以及整个系统中的线
		//程状况。从 ThreadMXBean 可以得到某一个线程的 ThreadInfo 对象。这个对象中则包含了这个
		//线程的所有信息。
		//线程的信息
		ThreadMXBean threadMXBean=ManagementFactory.getThreadMXBean();
		//所有的线程的编号
		long[] threadIds=threadMXBean.getAllThreadIds();
		for (long threadId : threadIds) {
			//线程的信息
			ThreadInfo  threadInfo=threadMXBean.getThreadInfo(threadId);
			//线程被阻塞的数量
			threadInfo.getBlockedCount();
			//被锁定线程的监控信息
			MonitorInfo[] monitorInfos=threadInfo.getLockedMonitors();
			for (MonitorInfo monitorInfo : monitorInfos) {
				int depth=monitorInfo.getLockedStackDepth();
				System.out.println("锁定的程度:"+depth);
			}
			//异步锁定的信息
			LockInfo[] lockinfos=threadInfo.getLockedSynchronizers();
			//锁定的信息
			for (LockInfo lockInfo : lockinfos) {
				System.out.println("锁定类的名称:"+lockInfo.getClassName());
			}
			//线程的名称
			String threadName=threadInfo.getThreadName();
			System.out.println("线程的名称:"+threadName);
			Thread.State state=threadInfo.getThreadState();
			System.out.println("线程的信息:"+state.name());
			
		}
		
		long cpuTime=threadMXBean.getCurrentThreadCpuTime();
		long curentTime=threadMXBean.getCurrentThreadUserTime();
		long threadCount=threadMXBean.getDaemonThreadCount();
		long peakliveThreadCount=threadMXBean.getPeakThreadCount();
		long threadCounts=threadMXBean.getThreadCount();
		System.out.println("当前处于live状态的线程总的数量:"+threadCounts);
		long totalThreadCount=threadMXBean.getTotalStartedThreadCount();
		System.out.println("JVM 启动之后,总的自动线程数量:"+totalThreadCount);
		
		
		
		
		
	}
	/**
	 * 
	 * @return
	 */
	public static final String getHeapMemoryUsage() {
		ClassLoadingMXBean mxbean;
		return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
				.getUsed()
				+ "/"
				+ ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
						.getMax();
	}
    /**
     * 当前使用内存的百分比
     * @return
     */
	public static final String getHeapMemoryUsagePercent() {
		return (((double) ManagementFactory.getMemoryMXBean()
				.getHeapMemoryUsage().getUsed() / (double) ManagementFactory
				.getMemoryMXBean().getHeapMemoryUsage().getMax()) * 100L)
				+ "%";
	}
    /**
     * 当前非java堆占用的百分比
     * @return
     */
	public static final String getNonHeapMemoryUsage() {
		return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()
				.getUsed()
				+ "/"
				+ ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()
						.getMax();
	}
	  /**
     * 
     * @return
     */
	public static final String getNonHeapMemoryUsagePercent() {
		return (((double) ManagementFactory.getMemoryMXBean()
				.getNonHeapMemoryUsage().getUsed() / (double) ManagementFactory
				.getMemoryMXBean().getNonHeapMemoryUsage().getMax()) * 100)
				+ "%";
	}
	  /**
     * 获取线程数
     * @return
     */
	public static final String getThreadCount() {
		return "" + ManagementFactory.getThreadMXBean().getThreadCount();
	}

}

 

Jsp页面:

<%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@page import="java.lang.management.ManagementFactory"%>
<%@page import="java.lang.management.MemoryUsage"%>
<%@page import="java.lang.management.ClassLoadingMXBean"%>
<%@page import="java.lang.management.CompilationMXBean"%>
<%@page import="java.lang.management.MemoryMXBean"%>
<%@page import="java.lang.management.RuntimeMXBean"%>
<%@page import="java.lang.management.ThreadMXBean"%>

<%@page import="java.util.Date"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%>

<%	
double oneMB =1024*1024;
String color = "blue";
MemoryMXBean memoryMXBean=ManagementFactory.getMemoryMXBean();  
    
    ClassLoadingMXBean classLoadMXBean=ManagementFactory.getClassLoadingMXBean();
    out.println("<label style=\"color: "+color+"\">===加载类的情况====</label><br />"); 
    out.println("加载类的总数量:"+classLoadMXBean.getTotalLoadedClassCount()+"个;<br />"); 
    out.println("已加载类的数量:"+classLoadMXBean.getLoadedClassCount()+"个;<br />");
    out.println("未加载类的数量:"+classLoadMXBean.getUnloadedClassCount()+"个;<br />");  
    out.println("是否开始加载类信息:"+classLoadMXBean.isVerbose()+";<br /><br />");  
       
    //CompilationMXBean 帮助用户了解当前的编译器和编译情况,该 mxbean 提供的信息不多。
    out.println("<label style=\"color: "+color+"\">===编译情况====</label><br />");   
    CompilationMXBean compilationMXBean=ManagementFactory.getCompilationMXBean();
    out.println("即时编译名称:"+compilationMXBean.getName()+";<br />");
    out.println("总的编译时间:"+compilationMXBean.getTotalCompilationTime()+"s;<br />");        
    
    boolean isSupport=compilationMXBean.isCompilationTimeMonitoringSupported();  
    if(isSupport){ 
     	out.println("是否支持监控:"+"支持即时编译器编译监控;<br /><br />");
    }else{  
    	out.println("是否支持监控:"+"不支持即时编译器编译监控;<br /><br />");            
    }  
    
    
    //堆得使用情况信息  
    MemoryUsage heapMemoryUsage=memoryMXBean.getHeapMemoryUsage();
    out.println("<label style=\"color: "+color+"\">===堆内存使用情况====</label><br />");
    out.println("当前使用内存:"+heapMemoryUsage.getUsed()/oneMB+"M;<br />"); 
    out.println("最大使用内存:"+heapMemoryUsage.getMax()/oneMB+"M;<br />");
    out.println("初始化时内存:"+heapMemoryUsage.getInit()/oneMB+"M;<br /><br />");  

	//java 非堆内存的使用情况  
	out.println("<label style=\"color: "+color+"\">===非堆内存的使用情况====</label><br />");

	MemoryMXBean memeoryMX = ManagementFactory.getMemoryMXBean();
	out.println("当前使用内存:"+memeoryMX.getNonHeapMemoryUsage().getUsed()/oneMB+"M;<br />");
	out.println("最大使用内存:"+memeoryMX.getNonHeapMemoryUsage().getMax()/oneMB+"M;<br />");
	out.println("初始化时内存:"+memeoryMX.getNonHeapMemoryUsage().getInit()/oneMB+"M;<br /><br />");
	
	
	 //线程的信息  
    ThreadMXBean threadMXBean=ManagementFactory.getThreadMXBean();  
	out.println("<label style=\"color: "+color+"\">===线程的信息====</label><br />");
	out.println("当前处于live状态的线程总的数量:"+threadMXBean.getThreadCount()+"个;<br />");
	out.println("JVM启动之后  ,总的自动线程数量:"+threadMXBean.getTotalStartedThreadCount()+"个;<br /><br />");

	out.println("<label style=\"color: "+color+"\">===服务器信息====</label><br />");
	RuntimeMXBean runtimeMX = ManagementFactory.getRuntimeMXBean();
	request.setAttribute("startTime", new Date(runtimeMX.getStartTime()));
	out.println("服务启动时间:"+new Date(runtimeMX.getStartTime())+";<br /><br />");
%>



 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值