5

我一直在研究为特定流程获取以下数据的最佳方法:

  1. CPU使用率
  2. 内存使用情况
  3. 磁盘使用情况
  4. 网络使用情况

我决定使用 OSHI(操作系统和硬件信息)API。对我来说不幸的是,这个 API 并没有给我开箱即用的所需信息,它需要一些关于如何计算的基本知识,例如每个进程的 cpu 使用率。

我的问题是:如何通过进程 id 获取内存、磁盘、网络使用情况?

使用以下每个进程的 cpu 使用数据示例

例如:

要获取 claculator.exe 运行进程的实际 CPU 使用率:

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;

public class processCPUusage {
    public static void main(String[] args) throws InterruptedException {
        OSProcess process;
        long currentTime,previousTime = 0,timeDifference;
        double cpu;
        int pid = 7132;
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        CentralProcessor processor = si.getHardware().getProcessor();
        int cpuNumber = processor.getLogicalProcessorCount();
        boolean processExists = true;
        while (processExists) {
            process = os.getProcess(pid); // calculator.exe process id
            if (process != null) {
                // CPU
                currentTime = process.getKernelTime() + process.getUserTime();

                if (previousTime != -1) {
                    // If we have both a previous and a current time
                    // we can calculate the CPU usage
                    timeDifference = currentTime - previousTime;
                    cpu = (100d * (timeDifference / ((double) 1000))) / cpuNumber;
                    System.out.println(cpu);
                }     

                previousTime = currentTime;

                Thread.sleep(1000);
            } else {
                processExists = false;
            }
        }
    }
}

我正在使用的框架 https://github.com/oshi/oshi/tree/master/src/site/markdown 演示了所需的功能,但缺少适当的示例

  • 语言:Java 8
  • 构建工具:Maven 2
  • 操作系统:Windows 10*

OSHI 库 + slf4j

    <dependency>
        <groupId>com.github.dblock</groupId>
        <artifactId>oshi-core</artifactId>
        <version>3.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>
4

2 回答 2

4

以下 2017 年的原始答案现已过时。该类OSProcess现在有更多的方法来主要回答原始请求。

Shikari的答案很适合手动计算。我还将注意到从 5.x 版本开始getProcessCpuLoadBetweenTicks()OSProcess对象上存在一个方法,该方法将为您进行 CPU 计算。

上一个答案如下:


我是在 OSHI 中实现您所引用的 OSProcess 类的人,并且一直在该项目的问题中与您沟通。

虽然 OSHI 目前并未提供OSProcess界面中的所有功能,但它确实为您提供了访问 WMI 类的方法,这些方法将为您提供您所寻找的所有信息。如果您查看实现您正在使用的方法的WindowsOperatingSystemgetProcess(),您可以复制/修改代码使用WMIUtil以直接获取您需要的信息位。

OSHI 目前从Win32_Process WMI 类获取信息,但正如我在该问题上所提到的,最好从Win32_PerfRawData_PerfProc_Process(它提供可用于直接计算的原始数据)或Win32_PerfFormattedData_PerfProc_Process获取信息。在这些课程中,您可以找到:

CPU使用率

  • 已用时间
  • 百分比特权时间
  • 百分比处理器时间
  • 百分比用户时间

(请注意,虽然名称为“百分比”,但原始数据实际上包括递增的“刻度”)

内存使用情况

  • 虚拟字节
  • 工作集

磁盘使用情况、网络使用情况

  • IOReadBytesPerSec;
  • IOWriteBytesPerSec;

在这些类中,磁盘和网络都合并在总数中。(同样,对于“原始数据”忽略“每秒”部分,它会增加总数据量)。

我不认为 Windows 在每个进程的基础上跟踪磁盘与网络 IO 的差异。

您应该采取的步骤:

  1. 使用所需的 WMI 字段名称定义逗号分隔的字符串

  2. ValueType以相同的顺序定义与字段名称匹配的类型的数组

  3. 执行Map<String, List<Object>> procs = WmiUtil.selectObjectsFrom(null, "Win32_PerfRawData_PerfProc_Process", processProperties, String.format("WHERE IdProcess=%d", pid), processPropertyTypes);

  4. 获取您想要使用的每个值procs.get("FieldNameHere").get(0)

于 2017-06-11T17:59:22.043 回答
3

主要方法

public static void main(String[] args) {
            int pid=8924;
            for (int i = 0; i < 10; i++) {
                diskUtilizationPerProcess(pid);
                memoryUtilizationPerProcess(pid);
                cpuUtilizationPerProcess(pid);
                Util.sleep(5000);
            }
        }

磁盘/IO:

public static  void diskUtilizationPerProcess(int pid) {
        /**
         * ByteRead : Returns the number of bytes the process has read from disk.
         * ByteWritten : Returns the number of bytes the process has written to disk.
         */
        OSProcess process;
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        process = os.getProcess(pid);
        System.out.println("\nDisk I/O Usage :");
        System.out.println("I/O Reads: "+process.getBytesRead());
        System.out.println("I/O Writes: "+process.getBytesWritten());
    }

CPU使用率 :

public static void cpuUtilizationPerProcess(int processId) {
        /**
         * User Time : Returns the number of milliseconds the process has executed in user mode.
         * Kernel Time : Returns the number of milliseconds the process has executed in kernel/system mode.
         */
        SystemInfo systemInfo = new SystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();
        int cpuNumber = processor.getLogicalProcessorCount();
        //int processId = systemInfo.getOperatingSystem().getProcessId();
        OSProcess process = systemInfo.getOperatingSystem().getProcess(processId);
        long currentTime = process.getKernelTime() + process.getUserTime();
        long timeDifference = currentTime - previousTime;
        double processCpu = (100 * (timeDifference / 5000d)) / cpuNumber;
        previousTime = currentTime;
        System.out.println("\nCPU Usage :");
        System.out.println("CPU : "+(int)processCpu+"%");
    }

内存使用情况

public static void memoryUtilizationPerProcess(int pid) {
        /**
         * Resident Size : how much memory is allocated to that process and is in RAM
         */
        OSProcess process;
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        process = os.getProcess(pid);
        System.out.println("\nMemory Usage :");
        System.out.println("Resident Size: "+process.getResidentSetSize());
    }
于 2020-09-18T19:17:48.857 回答