在本文中,我们了解到 OSHI 是一个功能强大但轻量级的 Java 库,用于检索系统和硬件信息。它消除了处理本机系统命令、JNI 或特定于平台的依赖项的麻烦,使其成为需要跨平台系统监控的开发人员的绝佳选择。
在本教程中,我们将学习一些有趣的东西,它们可以帮助我们了解我们的系统。每当我们考虑在 Java 中检查 CPU 使用率、内存状态或磁盘空间时,我们可能会问自己,“我需要调用系统命令或使用JNI吗?”不!这就是 OSHI(操作系统和硬件信息)的作用所在。
OSHI 是一个纯 Java 库,可帮助我们获取系统级详细信息,而无需任何本机依赖项。它充当 Java 应用程序和系统 API 之间的桥梁,以跨平台方式提取有关操作系统、硬件和网络的有用信息。
为什么使用OSHI进行系统监控?
我们可能会想,“为什么不直接使用Runtime.exec()或System.getProperty()呢?”因为这些方法有局限性。System.getProperty ()只能获取操作系统名称和版本,而Runtime.exec()需要特定于操作系统的命令。
另一方面,OSHI可与最流行的操作系统(Windows、macOS、Linux)配合使用。它提供有关 CPU、RAM、磁盘、传感器和网络的深度系统洞察。它不需要本机代码,因为它完全基于 Java,最后但并非最不重要的是,它轻量级且易于使用 - 我们只需要添加依赖项。
主要特点和优势
通过 OSHI,我们可以:
- 获取操作系统详细信息:名称、版本、架构和正常运行时间
- 监控 CPU 使用率、核心详细信息和处理器速度
- 获取内存统计信息:总 RAM、可用内存、交换使用情况
- 检索磁盘存储信息:分区、读/写速度
- 跟踪网络接口、IP 地址和带宽使用情况
- 访问传感器数据,如 CPU 温度、风扇速度和电压(如果支持)
现在,让我们进一步看看如何实现这些功能。在 Java 项目中设置 OSHI
在我们深入研究有趣的东西之前,让我们先将 OSHI 加入到我们的项目中。
如果我们使用 Maven,我们需要将oshi-core依赖项添加到我们的pom.xml中:
<dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>6.4.2</version> </dependency>
|
一旦添加,OSHI 就可以推出!检索基本系统信息
现在 OSHI 已经设置好了,让我们从基础开始:获取操作系统详细信息并检查系统正常运行时间。
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实例,该实例提供操作系统系列、版本和位数等信息。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)暂停两秒钟,处理中断。延迟后,它再次获取系统正常运行时间,这可用于验证正常运行时间是否随着时间的推移而增加。如果我们看到类似3600 秒这样的值,则表示我们的机器已经启动了一个小时。
使用 OSHI 监控 CPU
CPU(中央处理器)是任何系统的核心。监控其使用情况、负载和核心数量对于性能调优至关重要。
1. 获取处理器详细信息
OSHI 可以使用 Java 轻松获取处理器的名称、核心数量和时钟速度:
@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()返回逻辑处理器的数量,包括超线程核心。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 处于空闲状态,而较高的百分比表示工作负载较高。
内存监控
我们系统的 RAM(随机存取存储器)决定了可以同时运行多少个应用程序。
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 的内存报告。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 正确检测和报告磁盘信息。OSHI 的局限性
尽管 OSHI 功能丰富,但也存在一些局限性:
- 传感器数据可用性取决于硬件支持:并非所有机器都会显示温度或电压读数
- 有限的低级控制:OSHI 提供只读系统洞察;它不允许系统修改
- 对系统 API 的依赖:某些信息可能因操作系统不同而略有不同