package jef.tools.management;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import jef.common.log.LogUtil;
import jef.jre5support.ProcessUtil;
import jef.tools.IOUtils;
import jef.tools.StringUtils;
import jef.tools.collection.CollectionUtils;
import jef.tools.reflect.ClassEx;
import com.google.common.base.Function;
/**
* 这个Bean封装了JDK的OperatingSystemMXBean,可以根据SUN JDK(及其兼容),IBM JDK等 提供与JDK平台无关的扩展接口
*
* @author Administrator
*
*/
public class OperatingSystemMXBean implements java.lang.management.OperatingSystemMXBean {
private static OperatingSystemMXBean instance;
final static boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
final static boolean isHp = System.getProperty("os.name").toLowerCase().indexOf("hp") > -1;
private static String linuxVersion = System.getProperty("os.version");
private MemoryMXBean memMx;
private long maxPerm;
private long minPerm;
private long maxHeap;
private long minHeap;
private OperatingSystemMXBean() {
bean = ManagementFactory.getOperatingSystemMXBean();
ClassEx cw = new ClassEx(bean.getClass());
List<String> result = CollectionUtils.extract(cw.getAllInterfaces(), new Function<Class<?>,String>(){
public String apply(Class<?> input) {
return input.getName();
}
});
if (result.contains("com.sun.management.UnixOperatingSystemMXBean")) {
initSunJDKBean(cw);
} else if (result.contains("com.sun.management.OperatingSystemMXBean")) {
initSunJDKBean(cw);
} else if (result.contains("com.ibm.lang.management.OperatingSystemMXBean")) {
initIBMJDKBean(cw);
}
initMethodInJDK6(cw);
for (Method e : propertyMap.values()) {
e.setAccessible(true);
}
memMx=ManagementFactory.getMemoryMXBean();
MemoryUsage mu=memMx.getHeapMemoryUsage();
minHeap=mu.getInit();
maxHeap=mu.getMax();
mu=memMx.getNonHeapMemoryUsage();
minPerm=mu.getInit();
maxPerm=mu.getMax();
}
public static OperatingSystemMXBean getInstance() {
if (instance == null) {
instance = new OperatingSystemMXBean();
}
return instance;
}
private java.lang.management.OperatingSystemMXBean bean;
private Map<Attribute, Method> propertyMap = new HashMap<Attribute, Method>();
enum Attribute {
CommittedVirtualMemorySize, TotalSwapSpaceSize, FreeSwapSpaceSize, ProcessCpuTime, FreePhysicalMemorySize, TotalPhysicalMemorySize, SystemLoadAverage
}
/**
* 获取当前进程的pid
*
* @return
*/
public int getPid() {
return ProcessUtil.getPid();
}
/**
* 获取虚拟机的启动时间
*
* @return
*/
public Date getStartTime() {
return new Date(ProcessUtil.getStarttime());
}
/*
*
*/
private void initSunJDKBean(ClassEx cw) {
try {
propertyMap.put(Attribute.CommittedVirtualMemorySize, cw.getMethod("getCommittedVirtualMemorySize").getJavaMethod());
propertyMap.put(Attribute.FreePhysicalMemorySize, cw.getMethod("getFreePhysicalMemorySize").getJavaMethod());
propertyMap.put(Attribute.FreeSwapSpaceSize, cw.getMethod("getFreeSwapSpaceSize").getJavaMethod());
propertyMap.put(Attribute.ProcessCpuTime, cw.getMethod("getProcessCpuTime").getJavaMethod());
propertyMap.put(Attribute.TotalPhysicalMemorySize, cw.getMethod("getTotalPhysicalMemorySize").getJavaMethod());
propertyMap.put(Attribute.TotalSwapSpaceSize, cw.getMethod("getTotalSwapSpaceSize").getJavaMethod());
} catch (NoSuchMethodException e) {
LogUtil.exception(e);
}
}
private void initIBMJDKBean(ClassEx cw) {
try {
propertyMap.put(Attribute.TotalPhysicalMemorySize, cw.getMethod("getTotalPhysicalMemory").getJavaMethod());
} catch (NoSuchMethodException e) {
LogUtil.exception(e);
}
}
private void initMethodInJDK6(ClassEx cw) {
try {
propertyMap.put(Attribute.SystemLoadAverage, cw.getMethod("getSystemLoadAverage").getJavaMethod());
} catch (NoSuchMethodException e) {
}
}
/*
* (non-Javadoc)
*
* @see java.lang.management.OperatingSystemMXBean#getName()
*/
public String getName() {
return bean.getName();
}
/*
* (non-Javadoc)
*
* @see java.lang.management.OperatingSystemMXBean#getArch()
*/
public String getArch() {
return bean.getArch();
}
/*
* (non-Javadoc)
*
* @see java.lang.management.OperatingSystemMXBean#getVersion()
*/
public String getVersion() {
return bean.getVersion();
}
/*
* (non-Javadoc)
*
* @see java.lang.management.OperatingSystemMXBean#getAvailableProcessors()
*/
public int getAvailableProcessors() {
return bean.getAvailableProcessors();
}
/*
* 这个是JDK6才有的方法 (non-Javadoc)
*
* @see java.lang.management.OperatingSystemMXBean#getSystemLoadAverage()
*/
public double getSystemLoadAverage() {
if (!isWindows && propertyMap.containsKey(Attribute.SystemLoadAverage)) {
return invokeGet(propertyMap.get(Attribute.SystemLoadAverage), Double.class);
} else {
return getCpuRatio();
}
}
public long getHeapCommittedMemorySize(){
return memMx.getHeapMemoryUsage().getCommitted();
}
/**
* 获取最大的heap大小。一般由Xmx参数指定
* @return
*/
public long getMaxHeapSize(){
return maxHeap;
}
/**
* 获得初始的heap大小。一般由Xms参数指定
* @return
*/
public long getInitHeapSize(){
return minHeap;
}
/**
* 获取最大的Perm大小
* @return
*/
public long getMaxPermSize(){
return maxPerm;
}
/**
* 获的初始的Perm内存区域大小
* @return
*/
public long getInitPermSize(){
return minPerm;
}
/**
* 获取当前Heap内存的占用摘要信息
* @return
*/
public String getHeapMemoryUsage(){
return memMx.getHeapMemoryUsage().toString();
}
/**
* 获取当前Perm内存的占用摘要信息
* @return
*/
public String getPermMemoryUsage(){
return memMx.getNonHeapMemoryUsage().toString();
}
/**
* 获取目前操作系统已分配的内存数
*/
public long getCommittedVirtualMemorySize() {
return invokeGetLong(propertyMap.get(Attribute.CommittedVirtualMemorySize));
}
/**
* 当前系统总内存交换区
*
* @return
*/
public long getTotalSwapSpaceSize() {
return invokeGetLong(propertyMap.get(Attribute.TotalSwapSpaceSize));
}
/**
* 当前系统空闲交换区
*
* @return
*/
public long getFreeSwapSpaceSize() {
return invokeGetLong(propertyMap.get(Attribute.FreeSwapSpaceSize));
}
/**
* 当前进程的CPU时间
*
* @return
*/
public long getProcessCpuTime() {
return invokeGetLong(propertyMap.get(Attribute.ProcessCpuTime));
}
/**
* 当前系统的空闲物理内存
*
* @return
*/
public long getFreePhysicalMemorySize() {
return invokeGetLong(propertyMap.get(Attribute.FreePhysicalMemorySize));
}
/**
* 当前系统的物理内存
*
* @return
*/
public long getTotalPhysicalMemorySize() {
return invokeGetLong(propertyMap.get(Attribute.TotalPhysicalMemorySize));
}
@SuppressWarnings("unchecked")
private <T> T invokeGet(Method method, Class<T> clz) {
if (method == null) {
throw new UnsupportedOperationException();
}
try {
return (T) method.invoke(bean);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException());
}
}
private long invokeGetLong(Method method) {
return invokeGet(method, Long.class);
}
/**
* 取得CPU使用比例
*
* @return
* @deprecated 尽量不要用,使用命令方式不稳定,而却效率不高
*/
@Deprecated
private double getCpuRatio() {
double cpuRatio = 0;
if (isWindows) {
cpuRatio = getCpuRatioForWindows();
} else if (isHp) {
cpuRatio = getCpuRateForHP();
} else {
cpuRatio = getCpuRateForLinux();
}
return cpuRatio;
}
/**
* 当前系统是否windows
*
* @return
*/
public static boolean isWindows() {
return isWindows;
}
/**
* 获得当前的线程总数.
*
* 完成的线程 状态访问功能还是请使用
* ManagementFactory.getThreadMXBean();
* @return 返回构造好的监控对象
*/
public int getThreadCount(){
ThreadMXBean threadMx=ManagementFactory.getThreadMXBean();
return threadMx.getThreadCount();
}
private static double getCpuRateForLinux() {
BufferedReader brStat = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("top -b -n 1");
brStat = IOUtils.getReader(process.getInputStream(), "US-ASCII");
StringTokenizer tokenStat = null;
if (linuxVersion.startsWith("2.4")) {
brStat.readLine();
brStat.readLine();
brStat.readLine();
brStat.readLine();
tokenStat = new StringTokenizer(brStat.readLine());
tokenStat.nextToken();
tokenStat.nextToken();
String user = tokenStat.nextToken();
tokenStat.nextToken();
String system = tokenStat.nextToken();
tokenStat.nextToken();
String nice = tokenStat.nextToken();
// System.out.println(user + " , " + system + " , " + nice);
user = user.substring(0, user.indexOf("%"));
system = system.substring(0, system.indexOf("%"));
nice = nice.substring(0, nice.indexOf("%"));
float userUsage = new Float(user).floatValue();
float systemUsage = new Float(system).floatValue();
float niceUsage = new Float(nice).floatValue();
return (userUsage + systemUsage + niceUsage) / 100;
} else {
brStat.readLine();
brStat.readLine();
tokenStat = new StringTokenizer(brStat.readLine());
tokenStat.nextToken();
tokenStat.nextToken();
tokenStat.nextToken();
tokenStat.nextToken();
tokenStat.nextToken();
tokenStat.nextToken();
tokenStat.nextToken();
String cpuUsage = tokenStat.nextToken();
// System.out.println("CPU idle : " + cpuUsage);
Float usage = new Float(cpuUsage.substring(0, cpuUsage.indexOf("%")));
return (1 - usage.floatValue() / 100);
}
} catch (IOException e) {
LogUtil.exception(e);
return -1.0;
} finally {
if (process != null)
process.destroy();
IOUtils.closeQuietly(brStat);
}
}
/**
* 返回HP机器的CPU使用率
*
* @return
*/
private static double getCpuRateForHP() {
BufferedReader reader = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("top -n 1");
reader = IOUtils.getReader(process.getInputStream(), "US-ASCII");
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.startsWith("System Page Size") || line.length() == 0)
break;
if (line.startsWith("avg")) {
StringTokenizer st = new StringTokenizer(line);
for (int i = 0; i < 5; i++) {
st.nextToken();
}
String idle = st.nextToken().trim().replace("%", "");
return (100 - Double.parseDouble(idle)) / 100;
}
}
return -1.0;
} catch (IOException ioe) {
LogUtil.exception(ioe);
return -1.0;
} finally {
if (process != null)
process.destroy();
IOUtils.closeQuietly(reader);
}
}
/**
* 获得CPU使用率.
*
* @return 返回cpu使用率
*/
private static double getCpuRatioForWindows() {
try {
String procCmd = System.getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine," + "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
// 取进程信息
long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));
Thread.sleep(CPUTIME);
long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));
if (c0 != null && c1 != null) {
long idletime = c1[0] - c0[0];
long busytime = c1[1] - c0[1];
return Double.valueOf(PERCENT * (busytime) / (busytime + idletime)).doubleValue();
} else {
return 0.0;
}
} catch (Exception ex) {
LogUtil.error(ex.getMessage());
return 0.0;
}
}
private static final int CPUTIME = 30;
private static final int PERCENT = 100;
private static final int FAULTLENGTH = 10;
/**
*
* 读取CPU信息.
*
* @param proc
*/
private static long[] readCpu(final Process proc) {
long[] retn = new long[2];
try {
proc.getOutputStream().close();
InputStreamReader ir = new InputStreamReader(proc.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
String line = input.readLine();
if (line == null || line.length() < FAULTLENGTH) {
return null;
}
int capidx = line.indexOf("Caption");
int cmdidx = line.indexOf("CommandLine");
int rocidx = line.indexOf("ReadOperationCount");
int umtidx = line.indexOf("UserModeTime");
int kmtidx = line.indexOf("KernelModeTime");
int wocidx = line.indexOf("WriteOperationCount");
long idletime = 0;
long kneltime = 0;
long usertime = 0;
while ((line = input.readLine()) != null) {
if (line.length() < wocidx) {
continue;
}
String caption = line.substring(capidx, cmdidx - 1).trim();
String cmd = line.substring(cmdidx, kmtidx - 1).trim();
if (cmd.indexOf("wmic.exe") >= 0) {
continue;
}
if (caption.equals("System Idle Process") || caption.equals("System")) {
idletime += Long.valueOf(line.substring(kmtidx, rocidx - 1).trim()).longValue();
idletime += Long.valueOf(line.substring(umtidx, wocidx - 1).trim()).longValue();
continue;
}
kneltime += Long.valueOf(line.substring(kmtidx, rocidx - 1).trim()).longValue();
usertime += Long.valueOf(line.substring(umtidx, wocidx - 1).trim()).longValue();
}
retn[0] = idletime;
retn[1] = kneltime + usertime;
return retn;
} catch (Exception ex) {
LogUtil.exception(ex);
} finally {
IOUtils.closeQuietly(proc.getErrorStream());
}
return null;
}
/**
* 测试代码,由于需要在不同的平台上试运行。所以暂时都写在这个类里。
* @param args
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws Exception {
OperatingSystemMXBean bean=OperatingSystemMXBean.getInstance();
for(Method m:bean.getClass().getMethods()){
if(m.getParameterTypes().length==0 && m.getDeclaringClass()==OperatingSystemMXBean.class){
Object value=m.invoke(bean);
if(value instanceof Long){
if(m.getName().endsWith("Size")){
System.out.println(StringUtils.rightPad(m.getName(), 28)+"\t"+StringUtils.formatSize((Long)value));
}else if(m.getName().endsWith("getStartTime")){
System.out.println(StringUtils.rightPad(m.getName(), 28)+"\t"+new Date((Long)value));
}else{
System.out.println(StringUtils.rightPad(m.getName(), 28)+"\t"+value);
}
}else{
System.out.println(StringUtils.rightPad(m.getName(), 28)+"\t"+value);
}
}
}
}
public ObjectName getObjectName() {
try {
return ObjectName.getInstance("java.lang:type=OperatingSystem");
} catch (MalformedObjectNameException e) {
throw new RuntimeException();
} catch (NullPointerException e) {
throw new RuntimeException();
}
}
}