OSHI 是基于 JNA 的(本地)操作系统和硬件信息库。它不需要安装任何其他额外的本地库,旨在提供一种跨平台的实现来检索系统信息,例如操作系统版本、进程、内存和 CPU 使用率、磁盘和分区、设备、传感器等。

系统信息实体类:

import cn.hutool.core.lang.Singleton;
import cn.novelweb.tool.util.BigDecimalUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import oshi.hardware.CentralProcessor;
import oshi.hardware.CentralProcessor.TickType;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;
@Builder
@Data
@ApiModel(value = "系统信息整合")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SystemInfo {

/**
* 获取CPU需要睡眠的时间
*/
public static int OSHI_WAIT_SECOND = 500;

@ApiModelProperty(value = "系统CPU相关信息")
private CpuInfo cpuInfo = Singleton.get(CpuInfo.class);

@ApiModelProperty(value = "系统内存相关信息")
private MemoryInfo memoryInfo = Singleton.get(MemoryInfo.class);

@ApiModelProperty(value = "Java Jvm 相关信息")
private JvmInfo jvmInfo = Singleton.get(JvmInfo.class);

@ApiModelProperty(value = "操作系统相关信息")
private OsInfo osInfo = Singleton.get(OsInfo.class);

@ApiModelProperty(value = "磁盘相关信息")
private List<FileSystemInfo> fileSystemInfo = new LinkedList<>();

/**
* 实例化 SystemInfo
*/
public SystemInfo() {
info();
}

/**
* 初始化系统相关信息
*/
private void info() {
oshi.SystemInfo si = new oshi.SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
setCpuInfo(hal.getProcessor());
setMemoryInfo(hal.getMemory());
setJvmInfo();
setFileSystemInfo(si.getOperatingSystem());
}

/**
* 设置CPU相关信息
*
* @param processor 中央处理器信息
*/
private void setCpuInfo(CentralProcessor processor) {
// CPU信息
long[] prevTicks = processor.getSystemCpuLoadTicks();
// 这里必须要设置延迟
Util.sleep(OSHI_WAIT_SECOND);
long[] ticks = processor.getSystemCpuLoadTicks();
long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
long softIrq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
long ioWait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
long totalCpu = Math.max(user + nice + cSys + idle + ioWait + irq + softIrq + steal, 0);
DecimalFormat format = new DecimalFormat("#.00");
cpuInfo.setCpuNum(processor.getLogicalProcessorCount());
cpuInfo.setToTal(totalCpu);
cpuInfo.setSys(Double.parseDouble(format.format(cSys <= 0 ? 0 : (100d * cSys / totalCpu))));
cpuInfo.setUsed(Double.parseDouble(format.format(user <= 0 ? 0 : (100d * user / totalCpu))));
if (totalCpu == 0) {
cpuInfo.setWait(0);
} else {
cpuInfo.setWait(Double.parseDouble(format.format(100d * ioWait / totalCpu)));
}
cpuInfo.setFree(Double.parseDouble(format.format(idle <= 0 ? 0 : (100d * idle / totalCpu))));
cpuInfo.setCpuModel(processor.toString());
}

/**
* 设置内存信息
*/
private void setMemoryInfo(GlobalMemory memory) {
memoryInfo.setToTal(memory.getTotal());
memoryInfo.setUsed(memory.getTotal() - memory.getAvailable());
memoryInfo.setFree(memory.getAvailable());
}



/**
* 设置Java虚拟机
*/
private void setJvmInfo() {
Properties props = System.getProperties();
jvmInfo.setToTal(Runtime.getRuntime().totalMemory());
jvmInfo.setMax(Runtime.getRuntime().maxMemory());
jvmInfo.setFree(Runtime.getRuntime().freeMemory());
jvmInfo.setVersion(props.getProperty("java.version"));
jvmInfo.setHome(props.getProperty("java.home"));
}

/**
* 设置磁盘信息
*
* @param os 操作系统数据
*/
private void setFileSystemInfo(OperatingSystem os) {
FileSystem fileSystem = os.getFileSystem();
OSFileStore[] fsArray = fileSystem.getFileStores();
for (OSFileStore fs : fsArray) {
long free = fs.getUsableSpace();
long total = fs.getTotalSpace();
long used = total - free;
FileSystemInfo sysFile = new FileSystemInfo();
sysFile.setDirName(fs.getMount());
sysFile.setSysTypeName(fs.getType());
sysFile.setTypeName(fs.getName());
sysFile.setToTal(convertFileSize(total));
sysFile.setFree(convertFileSize(free));
sysFile.setUsed(convertFileSize(used));
sysFile.setUsage(BigDecimalUtil.mul(BigDecimalUtil.div(used, total, 4), 100));
fileSystemInfo.add(sysFile);
}
}

/**
* 文件大小字节转换
*
* @param size 大小
* @return 转换后的字符串
*/
private String convertFileSize(long size) {
long kb = 1024;
long mb = kb * 1024;
long gb = mb * 1024;
if (size >= gb) {
return String.format("%.1f GB", (float) size / gb);
} else if (size >= mb) {
float f = (float) size / mb;
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
} else if (size >= kb) {
float f = (float) size / kb;
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
} else {
return String.format("%d B", size);
}
}
}

cpu信息:

@Data
@ApiModel(value = "系统CPU相关信息")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CpuInfo {

@ApiModelProperty(value = "cpu核心数", example = "0")
private Integer cpuNum;

@ApiModelProperty(value = "CPU总的使用率", example = "0.00")
private double toTal;

@ApiModelProperty(value = "CPU系统使用率", example = "0.00")
private double sys;

@ApiModelProperty(value = "CPU用户使用率", example = "0.00")
private double used;

@ApiModelProperty(value = "CPU当前等待率", example = "0.00")
private double wait;

@ApiModelProperty(value = "CPU当前空闲率", example = "0.00")
private double free;

@ApiModelProperty(value = "CPU型号信息")
private String cpuModel;
}

系统内存信息:

@Data
@ApiModel(value = "系统内存相关信息")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MemoryInfo {

@ApiModelProperty(value = "内存总量(GB)", example = "0.00")
private double toTal;

@ApiModelProperty(value = "已用内存(GB)", example = "0.00")
private double used;

@ApiModelProperty(value = "剩余内存(GB)", example = "0.00")
private double free;

@ApiModelProperty(value = "当前内存使用率(百分比)", example = "0.00")
private double usage;

public double getTotal() {
return BigDecimalUtil.div(toTal, (1024 * 1024 * 1024), 2);
}

public double getUsed() {
return BigDecimalUtil.div(used, (1024 * 1024 * 1024), 2);
}

public double getFree() {
return BigDecimalUtil.div(free, (1024 * 1024 * 1024), 2);
}

public double getUsage() {
return BigDecimalUtil.mul(BigDecimalUtil.div(used, toTal, 4), 100);
}
}

jvm信息:

@Data
@ApiModel(value = "Java Jvm 相关信息")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class JvmInfo {

@ApiModelProperty(value = "当前JVM占用的内存总数(M)", example = "0.00")
private double toTal;

@ApiModelProperty(value = "JVM最大可用内存总数(M)", example = "0.00")
private double max;

@ApiModelProperty(value = "JVM空闲内存(M)", example = "0.00")
private double free;

@ApiModelProperty(value = "JVM的启动时间")
private String startTime;

@ApiModelProperty(value = "JVM的运行时间")
private String runTime;

@ApiModelProperty(value = "当前JVM运行的PID")
private Long currentProcessIdentifier;

@ApiModelProperty(value = "当前JVM已经使用的部分")
private String used;

@ApiModelProperty(value = "当前JVM使用率(百分比)")
private String usage;

@ApiModelProperty(value = "JDK版本信息")
private String version;

@ApiModelProperty(value = "JDK安装路径")
private String home;

@ApiModelProperty(value = "JDK名称")
private String name;

public double getToTal() {
return BigDecimalUtil.div(toTal, (1024 * 1024), 2);
}

public double getMax() {
return BigDecimalUtil.div(max, (1024 * 1024), 2);
}

public double getFree() {
return BigDecimalUtil.div(free, (1024 * 1024), 2);
}

public String getName() {
return ManagementFactory.getRuntimeMXBean().getVmName();
}

public String getStartTime() {
return DateUtil.formatDateTime(getServerStartDate());
}

public String getRunTime() {
return getDatePoor(new Date(), getServerStartDate());
}

public Long getCurrentProcessIdentifier() {
return Long.parseLong(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
}

public double getUsed() {
return BigDecimalUtil.div(toTal - free, (1024 * 1024), 2);
}

public double getUsage() {
return BigDecimalUtil.mul(BigDecimalUtil.div(toTal - free, toTal, 4), 100);
}

/**
* 获取JVM服务启动时间
*
* @return 返回Date形式的JVM启动时间
*/
private static Date getServerStartDate() {
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}

/**
* 获取两个时间的差值(用于计算JVM运行时间)
*
* @param endDate 大的那个时间
* @param nowDate 小的那个时间
* @return 返回差的时间字符
*/
private static String getDatePoor(Date endDate, Date nowDate) {
// 依次定义 天、时、分、秒
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 输出结果
return DateUtil.formatBetween(diff, BetweenFormater.Level.SECOND);
}
}