简体   繁体   English

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

[英]Java (Windows) - By process id, get memory usage, disk usage, network usage

I've been investigating the best approach to achieve the following data for a specific process:我一直在研究为特定过程实现以下数据的最佳方法:

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

I decided to go with OSHI (Operating system & hardware information) API.我决定使用 OSHI(操作系统和硬件信息)API。 Unfortunate for me , this API isn't giving me the desired info out of the box, it requires some basic knowledge of how to calculate , for example the cpu usage per process.对我来说不幸的是,这个 API 没有给我开箱即用的信息,它需要一些关于如何计算的基本知识,例如每个进程的 CPU 使用率。

My Question is: How can I get the memory, disk, network usage by process id ?我的问题是:如何通过进程 id 获取内存、磁盘、网络使用情况?

using the following example of cpu usage data per prcoess使用以下每个进程的 CPU 使用数据示例

For example:例如:

To get the actual CPU usage of a claculator.exe running process:要获取 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;
            }
        }
    }
}

The framework I'm using https://github.com/oshi/oshi/tree/master/src/site/markdown demonstrates the desired functionality but lacks proper examples我使用的框架https://github.com/oshi/oshi/tree/master/src/site/markdown演示了所需的功能,但缺乏适当的示例

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

OSHI library + slf4j 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>

The original answer in 2017 below is now out of date.以下 2017 年的原始答案现已过时。 The OSProcess class now has many more methods that mostly answer the original request. OSProcess类现在有更多的方法,主要回答原始请求。

The answer by Shikari is good for manual calculations. Shikari答案适用于手动计算。 I'll also note the presence of a method getProcessCpuLoadBetweenTicks() on the OSProcess object starting in version 5.x that will do the CPU calculation for you.我还将注意到从版本 5.x 开始的OSProcess对象上存在一个getProcessCpuLoadBetweenTicks()方法,该方法将为您进行 CPU 计算。

Previous answer below:以前的答案如下:


I am the one who implemented the OSProcess class in OSHI that you are referencing, and have been communicating with you in an Issue on that project.我是在您所引用的 OSHI 中实现 OSProcess 类的人,并且一直在该项目的问题中与您进行交流。

While OSHI does not currently provide all the functionality in the OSProcess interface, it does provide you access methods to the WMI classes which will provide you all the information you seek.虽然 OSHI 当前并未提供OSProcess接口中的所有功能,但它确实为您提供了对 WMI 类的访问方法,这些方法将为您提供所需的所有信息。 If you take a look at the WindowsOperatingSystem class which implements the getProcess() method you're using, you can copy/modify the code using WMIUtil to directly fetch the bits of information that you need.如果您查看实现您正在使用的getProcess()方法的WindowsOperatingSystem类,您可以使用WMIUtil复制/修改代码以直接获取您需要的信息位。

OSHI currently fetches from theWin32_Process WMI class but as I've mentioned on the issue, it might be better to get information instead fromWin32_PerfRawData_PerfProc_Process (which provides the raw data you can use for direct calculations) or Win32_PerfFormattedData_PerfProc_Process . OSHI 当前从Win32_Process WMI 类中获取,但正如我在这个问题上提到的,最好从Win32_PerfRawData_PerfProc_Process (它提供可用于直接计算的原始数据)或Win32_PerfFormattedData_PerfProc_Process 获取信息 In these classes you can find:在这些课程中,您可以找到:

CPU usage CPU使用率

  • ElapsedTime已用时间
  • PercentPrivilegedTime特权时间百分比
  • PercentProcessorTime处理器时间百分比
  • PercentUserTime百分比用户时间

(Note while the name says "Percent" the raw data actually includes incrementing "ticks") (请注意,虽然名称为“百分比”,但原始数据实际上包括递增的“刻度”)

Memory usage内存使用情况

  • VirtualBytes虚拟字节
  • WorkingSet工作集

Disk usage, Network usage磁盘使用率、网络使用率

  • IOReadBytesPerSec; IOReadBytesPerSec;
  • IOWriteBytesPerSec; IOWriteBytesPerSec;

In these classes, both Disk and Network are combined in the totals.在这些类中,磁盘和网络都合并在总数中。 (Again, for the "raw data" ignore the "per sec" part, it will give increasing total amounts of data). (同样,对于“原始数据”忽略“每秒”部分,它将提供越来越多的数据总量)。

I do not think Windows keeps track of the difference in Disk vs. Network IO on a per-process basis.我认为 Windows 不会在每个进程的基础上跟踪磁盘与网络 IO 的差异。

Steps you should take:你应该采取的步骤:

  1. Define a comma-separated string with the WMI field names you want使用您想要的 WMI 字段名称定义一个以逗号分隔的字符串

  2. Define a ValueType array with types matching the field names, in the same order以相同的顺序定义一个类型与字段名称匹配的ValueType数组

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

  4. Fetch each value you want using procs.get("FieldNameHere").get(0)使用procs.get("FieldNameHere").get(0)获取您想要的每个值

Main Method主要方法

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

Disk/IO :磁盘/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 Usage : 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+"%");
    }

Memory Usage内存使用情况

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM