Java做Web开发时,有时需要实时查看操作系统资源占用情况,以便分析应用是否发生高耗或异常。
1. 引入支持库
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>5.3.6</version>
</dependency>
2. 编写测试代码
package org.dsg.oshi;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUtil;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.VirtualMemory;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.FormatUtil;
import oshi.util.Util;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.DecimalFormat;
import java.util.*;
public class OSMonitorService {
public static void main(String[] args) {
OSMonitorService service = new OSMonitorService();
Map<String, Object> servers = service.getServers();
if(CollectionUtil.isNotEmpty(servers)) {
servers.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
/**
* 定义GB的计算常量
*/
private static final int GB = 1024 * 1024 * 1024;
/**
* 定义MB的计算常量
*/
private static final int MB = 1024 * 1024;
/**
* 定义KB的计算常量
*/
private static final int KB = 1024;
private final DecimalFormat df = new DecimalFormat("0.00");
/**
* 获取服务器信息
*/
private Map<String, Object> getServers(){
Map<String, Object> resultMap = new LinkedHashMap<>(8);
try{
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
HardwareAbstractionLayer hal = si.getHardware();
resultMap.put("sys", getSystemInfo(os));
resultMap.put("cpu", getCpuInfo(hal.getProcessor()));
resultMap.put("memory", getMemoryInfo(hal.getMemory()));
resultMap.put("swap", getSwapInfo(hal.getMemory()));
resultMap.put("disk", getDiskInfo(os));
resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss"));
}catch(Exception e){
e.printStackTrace();
return null;
}
return resultMap;
}
/**
* 获取磁盘信息
*/
private Map<String, Object> getDiskInfo(OperatingSystem os){
Map<String, Object> diskInfo = new LinkedHashMap<>();
FileSystem fileSystem = os.getFileSystem();
List<OSFileStore> fsArray = fileSystem.getFileStores();
String osName = System.getProperty("os.name");
long available = 0, total = 0;
for(OSFileStore fs:fsArray){
// windows 需要将所有磁盘分区累加,linux 和 mac 直接累加会出现磁盘重复的问题,待修复
if(osName.toLowerCase().startsWith("win")){
available += fs.getUsableSpace();
total += fs.getTotalSpace();
}else{
available = fs.getUsableSpace();
total = fs.getTotalSpace();
break;
}
}
long used = total - available;
diskInfo.put("total", total > 0?getSize(total):"?");
diskInfo.put("available", getSize(available));
diskInfo.put("used", getSize(used));
diskInfo.put("usageRate", df.format(used/(double)total*100));
return diskInfo;
}
/**
* 获取交换区信息
*/
private Map<String, Object> getSwapInfo(GlobalMemory memory){
Map<String, Object> swapInfo = new LinkedHashMap<>();
VirtualMemory virtualMemory = memory.getVirtualMemory();
long total = virtualMemory.getSwapTotal();
long used = virtualMemory.getSwapUsed();
swapInfo.put("total", FormatUtil.formatBytes(total));
swapInfo.put("used", FormatUtil.formatBytes(used));
swapInfo.put("available", FormatUtil.formatBytes(total - used));
if(used == 0){
swapInfo.put("usageRate", 0);
}else{
swapInfo.put("usageRate", df.format(used/(double)total*100));
}
return swapInfo;
}
/**
* 获取内存信息
*/
private Map<String, Object> getMemoryInfo(GlobalMemory memory){
Map<String, Object> memoryInfo = new LinkedHashMap<>();
memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal()));
memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable()));
memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable()));
memoryInfo.put("usageRate", df.format((memory.getTotal() - memory.getAvailable())/(double)memory.getTotal()*100));
return memoryInfo;
}
/**
* 获取CPU相关信息
*/
private Map<String, Object> getCpuInfo(CentralProcessor processor){
Map<String, Object> cpuInfo = new LinkedHashMap<>();
cpuInfo.put("name", processor.getProcessorIdentifier().getName());
cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理包数");
cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心");
cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount());
cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU");
long[] prevTicks = processor.getSystemCpuLoadTicks();
Util.sleep(1000);
long[] ticks = processor.getSystemCpuLoadTicks();
long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];;
long ioWait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long totalCPU = user + nice + sys + idle + ioWait + irq + softIrq + steal;
cpuInfo.put("used", df.format(100d * user / totalCPU + 100d * sys / totalCPU));
cpuInfo.put("idle", df.format(100d * idle / totalCPU));
return cpuInfo;
}
/**
* 获取系统相关信息,系统运行天数、系统IP
*/
private Map<String, Object> getSystemInfo(OperatingSystem os){
Map<String, Object> systemInfo = new LinkedHashMap<>();
//JVM运行事件
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
Date date = new Date(time);
//计算项目运行时间
String formatBetween = DateUtil.formatBetween(date, new Date(), BetweenFormater.Level.HOUR);
//系统信息
systemInfo.put("os", os.toString());
systemInfo.put("day", formatBetween);
systemInfo.put("ip", getLocalIP());
return systemInfo;
}
/**
* 获取当前机器IP
* 遍历所有的网络接口,在所有的接口下遍历IP,排除loopback类型地址
* 如果没有非loopback类型地址,只能用最次选的方案
*/
private static String getLocalIP(){
try {
InetAddress candidateAddress = null;
//遍历网络接口
for(Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();){
NetworkInterface networkInterface = interfaces.nextElement();
for(Enumeration<InetAddress> iNetAddress = networkInterface.getInetAddresses(); iNetAddress.hasMoreElements();){
InetAddress inetAddress = iNetAddress.nextElement();
if(!inetAddress.isLoopbackAddress()){
if(inetAddress.isSiteLocalAddress()){
return inetAddress.getHostAddress();
}else if(candidateAddress == null){
candidateAddress = inetAddress;
}
}
}
}
if(candidateAddress != null){
return candidateAddress.getHostAddress();
}
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
if(jdkSuppliedAddress == null) {
return "";
}
return jdkSuppliedAddress.getHostAddress();
}catch(Exception e){
return "";
}
}
private String getSize(long size) {
String resultSize;
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
resultSize = df.format(size / (float) GB) + "GB";
} else if (size / MB >= 1) {
//如果当前Byte的值大于等于1MB
resultSize = df.format(size / (float) MB) + "MB";
} else if (size / KB >= 1) {
//如果当前Byte的值大于等于1KB
resultSize = df.format(size / (float) KB) + "KB";
} else {
resultSize = size + "B ";
}
return resultSize;
}
}