Java(Windows) - 按进程ID,获取内存使用情况,磁盘使用情况,网络使用情况

时间:2017-06-10 15:05:51

标签: java windows jna

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

  1. CPU使用率
  2. 内存使用
  3. 磁盘使用情况
  4. 网络使用
  5. 我决定使用OSHI(操作系统和硬件信息)API。 不幸的是,这个API并没有提供开箱即用的所需信息,它需要一些如何计算的基本知识,例如每个进程的CPU使用率。

    我的问题是:如何按流程ID获取内存,磁盘和网络使用情况?

    使用以下每个prcoess的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>
    

2 个答案:

答案 0 :(得分:2)

主要方法

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());
    }

答案 1 :(得分:1)

我是在您正在引用的OSHI中实现OSProcess类的人,并且已经在该项目的问题中与您进行了沟通。

虽然OSHI目前不提供OSProcess接口中的所有功能,但它确实为您提供了WMI类的访问方法,这些方法将为您提供所需的所有信息。如果你看一下实现你正在使用的getProcess()方法的WindowsOperatingSystem类,你可以使用WMIUtil复制/修改代码,直接获取你需要的信息。

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

CPU使用率

  • ElapsedTime
  • PercentPrivilegedTime
  • PercentProcessorTime
  • PercentUserTime

(注意,当名称显示“百分比”时,原始数据实际上包括递增“滴答”)

内存使用情况

  • VirtualBytes
  • 工作集

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

  • 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)

  5. 获取所需的每个值