1. 概述
在本教程中,我们将学习一些有趣的东西,可以帮助我们了解我们的系统。每当我们想在Java中检查CPU使用率、内存状态或磁盘空间时,我们可能会问自己,“我需要调用系统命令或使用JNI吗?” 不,这就是OSHI的作用所在。
OSHI是一个纯Java库,可帮助我们获取系统级详细信息,而无需任何本机依赖。它充当Java应用程序和系统API之间的桥梁,以跨平台方式提取有关操作系统、硬件和网络的有用信息。
2. 为什么使用OSHI进行系统监控?
我们可能会想,“为什么不直接使用Runtime.exec()或System.getProperty()呢?”,因为这些方法有局限性,System.getProperty()只能获取操作系统名称和版本,而Runtime.exec()需要特定于操作系统的命令。
另一方面,OSHI可与最流行的操作系统(Windows、macOS、Linux)配合使用,它提供有关CPU、RAM、磁盘、传感器和网络的深度系统洞察。它不需要本机代码,因为它完全基于Java,最后但并非最不重要的是,它轻量级且易于使用-我们只需要添加依赖。
3. 主要特点和优势
通过OSHI,我们可以:
- 获取操作系统详细信息:名称、版本、架构和正常运行时间
- 监控CPU使用率、核心详细信息和处理器速度
- 获取内存统计信息:总RAM、可用内存、交换使用情况
- 检索磁盘存储信息:分区、读/写速度
- 跟踪网络接口、IP地址和带宽使用情况
- 访问传感器数据,如CPU温度、风扇速度和电压(如果支持)
现在,让我们进一步看看如何实现这些功能。
4. 在Java项目中设置OSHI
在深入研究有趣的东西之前,让我们先将OSHI添加到项目中。
如果我们使用Maven,我们需要将oshi-core依赖项添加到pom.xml中:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.4.2</version>
</dependency>
5. 检索基本系统信息
现在OSHI已经设置好了,让我们从基础开始:获取操作系统详细信息并检查系统正常运行时间。
5.1 获取操作系统详细信息
如果想知道我们运行的是什么操作系统、哪个版本以及是32位还是64位,让我们看看使用OSHI怎么做到这一点:
@Test
void givenSystem_whenUsingOSHI_thenExtractOSDetails() {
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
assertNotNull(os, "Operating System object should not be null");
assertNotNull(os.getFamily(), "OS Family should not be null");
assertNotNull(os.getVersionInfo(), "OS Version info should not be null");
assertTrue(os.getBitness() == 32 || os.getBitness() == 64, "OS Bitness should be 32 or 64");
}
该代码从OSHI库创建一个SystemInfo对象来访问与系统相关的详细信息,然后,它会检索OperatingSystem实例,该实例提供操作系统系列、版本和位数等信息。
5.2 检查系统正常运行时间
我们也可以检查系统运行了多久时间:
@Test
void givenSystem_whenUsingOSHI_thenExtractSystemUptime() {
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
long uptime = os.getSystemUptime();
assertTrue(uptime >= 0, "System uptime should be non-negative");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
fail("Test interrupted");
}
long newUptime = os.getSystemUptime();
assertTrue(newUptime >= uptime, "Uptime should increase over time");
}
在这里,我们通过创建SystemInfo对象并访问OperatingSystem实例,使用OSHI检索系统正常运行时间。测试首先检查系统正常运行时间是否为非负数,以确保值有效。然后,它使用Thread.sleep(2000)暂停2秒钟,处理中断。延迟后,它再次获取系统正常运行时间,这可用于验证正常运行时间是否随着时间的推移而增加。
如果我们看到类似3600秒这样的值,则表示我们的机器已经启动了一个小时。
6. 使用OSHI监控CPU
CPU(中央处理器)是任何系统的核心,监控其使用情况、负载和核心数量对于性能调优至关重要。
6.1 获取处理器详细信息
OSHI可以轻松获取处理器的名称、核心数量和时钟速度:
@Test
void givenSystem_whenUsingOSHI_thenExtractCPUDetails() {
SystemInfo si = new SystemInfo();
CentralProcessor processor = si.getHardware().getProcessor();
assertNotNull(processor, "Processor object should not be null");
assertTrue(processor.getPhysicalProcessorCount() > 0, "CPU must have at least one physical core");
assertTrue(processor.getLogicalProcessorCount() >= processor.getPhysicalProcessorCount(), "Logical cores should be greater than or equal to physical cores");
}
此测试从OSHI初始化SystemInfo对象并从系统硬件中检索CentralProcessor实例,CentralProcessor提供有关CPU的详细信息,例如核心数、处理器标识符和负载指标,但此代码段中不存在任何断言或验证。
方法processor.getPhysicalProcessorCount()返回系统中的物理CPU核心数,它确保系统至少有一个物理核心,而processor.getLogicalProcessorCount()返回逻辑处理器的数量,包括超线程核心。
6.2 动态测量CPU负载
如果我们想检查CPU在某一时刻的繁忙程度,我们可以轻松地做到这一点:
@Test
void givenSystem_whenUsingOSHI_thenExtractCPULoad() throws InterruptedException {
SystemInfo si = new SystemInfo();
CentralProcessor processor = si.getHardware().getProcessor();
long[] prevTicks = processor.getSystemCpuLoadTicks();
TimeUnit.SECONDS.sleep(1);
double cpuLoad = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
assertTrue(cpuLoad >= 0 && cpuLoad <= 100, "CPU load should be between 0% and 100%");
}
代码捕获系统的CPU负载周期(prevTicks),等待一秒钟,然后使用getSystemCpuLoadBetweenTicks(prevTicks) * 100计算记录的周期之间的CPU负载百分比。最后,它断言CPU负载在0%到100%的有效范围内,确保OSHI报告的CPU利用率的正确性。
较低的百分比表示我们的CPU处于空闲状态,而较高的百分比表示工作负载较高。
7. 内存监控
我们系统的RAM(随机存取存储器)决定了可以同时运行多少个应用程序。
7.1 检索总RAM和可用RAM
让我们看看如何检索系统的总RAM和可用RAM:
@Test
void givenSystem_whenUsingOSHI_thenExtractMemoryDetails() {
SystemInfo si = new SystemInfo();
GlobalMemory memory = si.getHardware().getMemory();
assertTrue(memory.getTotal() > 0, "Total memory should be positive");
assertTrue(memory.getAvailable() >= 0, "Available memory should not be negative");
assertTrue(memory.getAvailable() <= memory.getTotal(), "Available memory should not exceed total memory");
}
代码初始化SystemInfo对象并获取GlobalMemory实例,该实例提供与内存相关的信息。它断言总内存为正数,确保系统具有有效RAM;它还检查可用内存是否为非负数且不超过总内存,从而验证OSHI的内存报告。
7.2 存储和磁盘信息
硬盘和SSD存储我们所有的数据,OSHI可帮助监控总磁盘空间、分区和使用情况统计数据:
@Test
void givenSystem_whenUsingOSHI_thenExtractDiskDetails() {
SystemInfo si = new SystemInfo();
List<HWDiskStore> diskStores = si.getHardware().getDiskStores();
assertFalse(diskStores.isEmpty(), "There should be at least one disk");
for (HWDiskStore disk : diskStores) {
assertNotNull(disk.getModel(), "Disk model should not be null");
assertTrue(disk.getSize() >= 0, "Disk size should be non-negative");
}
}
代码使用OSHI检索磁盘存储详细信息,它获取代表系统磁盘的HWDiskStore实例列表。它确保至少有一个磁盘存在,然后遍历每个磁盘,验证型号名称不为空且磁盘大小非负,这确保OSHI正确检测和报告磁盘信息。
8. OSHI的局限性
尽管OSHI功能丰富,但也存在一些局限性:
- 传感器数据可用性取决于硬件支持:并非所有机器都会显示温度或电压读数
- 有限的低级控制:OSHI提供只读系统洞察;它不允许系统修改
- 对系统API的依赖:某些信息可能因操作系统不同而略有不同
9. 总结
在本文中,我们了解到OSHI是一个功能强大但轻量级的Java库,用于检索系统和硬件信息。它消除了处理本机系统命令、JNI或特定于平台的依赖的麻烦,使其成为需要跨平台系统监控的开发人员的绝佳选择。
Post Directory
