OSHI简介

2025/04/11

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或特定于平台的依赖的麻烦,使其成为需要跨平台系统监控的开发人员的绝佳选择。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章