0

I want to implement a test program which calculates the CPU Usage using the Java Management API properly. The result should be the artihmetic mean over all processors and their cores. The problem on a windows machine is that the standard methods

ManagementFactory.getOperatingSystemMXBean().

(a) getSystemLoadAverage()
(b) getProcessCpuLoad()
(c) getSystemCpuLoad()

deliver too often the value -1.00 which means that the cpu usage could not be calculated. The standard methods work fine on linux, but not on windows. I also searched for the solution in this forum. I found in this forum some approaches to solve this problem, but none of them are helpful for me. For, example the code below always calculates 16 % on my machine which is not realistically.

public synchronized double getCpuUsage() {
    double cpuPercent = 0.0;

    for (int i = 0; i < 30; i++) {
        long start = System.nanoTime();
        int cpuCount = getOperatingSystemMxBean().getAvailableProcessors();
        Random random = new Random(start);
        int seed = Math.abs(random.nextInt());
        int primes = 10000;
        long startCpuTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();
        start = System.nanoTime();
        while (primes != 0) {
            if (isPrime(seed))
            {
                primes--;
            }
            seed++;
        } 

        cpuPercent = calcCpu(startCpuTime, start, cpuCount);

        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    return cpuPercent;
}

static boolean isPrime(int n) {
    // 2 is the smallest prime
    if (n <= 2)
    {
        return n == 2;
    }

    // even numbers other than 2 are not prime
    if (n % 2 == 0) {
        return false;
    }

    //check odd divisory from 3
    // to the square root of n
    for (int i = 3, end = (int)Math.sqrt(n); i <= end; i += 2) {
        if (n % i == 0)  {
            return false;
        }
    }

    return true;
}

public static int calcCpu(long cpuStartTime, long elapsedStartTime, int cpuCount) {
    long end = System.nanoTime();
    long totalAvailCpuTime = cpuCount * (end - elapsedStartTime);
    long totalUsedCpuTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime() - cpuStartTime;
    float per = ((float)totalUsedCpuTime*100) / (float)totalAvailCpuTime;
    //log (per);
    return (int)per;
}

private OperatingSystemMXBean getOperatingSystemMxBean() {
    return (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
}

Do you know a proper solution for this problem?

1 Answers1

0

I solved the problem in the windows machine by using the library oshi. On Solaris and Linux I continue using the Java Management API.