Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
  2. Memory usage
  3. Disk usage
  4. Network usage

I decided to go with OSHI (Operating system & hardware information) 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.

My Question is: How can I get the memory, disk, network usage by process id ?

using the following example of cpu usage data per prcoess

For example:

To get the actual CPU usage of a claculator.exe running process:

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

  • Language: Java 8
  • Build tool: Maven 2
  • OS: Windows 10*

OSHI library + 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>
like image 336
Benma Avatar asked Jun 10 '17 15:06

Benma


1 Answers

The original answer in 2017 below is now out of date. The OSProcess class now has many more methods that mostly answer the original request.

The answer by Shikari is good for manual calculations. 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.

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.

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. 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.

OSHI currently fetches from the Win32_Process WMI class but as I've mentioned on the issue, it might be better to get information instead from Win32_PerfRawData_PerfProc_Process (which provides the raw data you can use for direct calculations) or Win32_PerfFormattedData_PerfProc_Process. In these classes you can find:

CPU usage

  • 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;
  • 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.

Steps you should take:

  1. Define a comma-separated string with the WMI field names you want

  2. Define a ValueType array with types matching the field names, in the same order

  3. Execute 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)

like image 94
Daniel Widdis Avatar answered Oct 04 '22 00:10

Daniel Widdis