17

Is there a way in monitoring CPU usage using pure Java?

6 Answers 6

10

There is a gem in the comments on the article which kgiannakakis linked:

javasysmon

JavaSysMon manages processes and reports useful system performance metrics cross-platform. You can think of it as a cross-platform version of the UNIX `top’ command, along with the ability to kill processes. It comes in the form of a single JAR file /..

-works on Windows, Mac OS X, Linux, and Solaris.

Sign up to request clarification or add additional context in comments.

Comments

7

How about using jmx mbeans?

final OperatingSystemMXBean myOsBean= 
            ManagementFactory.getOperatingSystemMXBean();
double load = myOsBean.getSystemLoadAverage();

3 Comments

Gives -1 for me on Windows platforms.
docs says -1 means not supported. But on linux I get value less than what OS says, so I assume it is the CPU load used by current JVM?
6

You can use jMX beans to calculate a CPU load. Note that this measures CPU load of your java program, not the overall system load. (the question didn't specify which)

Initialize:

    ThreadMXBean newBean = ManagementFactory.getThreadMXBean();
    try
    {
        if (this.newBean.isThreadCpuTimeSupported())
            this.newBean.setThreadCpuTimeEnabled(true);
        else
            throw new AccessControlException("");
    }
    catch (AccessControlException e)
    {
        System.out.println("CPU Usage monitoring is not available!");
        System.exit(0);
    }

Then as your loop (assuming your application uses a loop, otherwise what's the point in measuring CPU usage?) use this:

    long lastTime = System.nanoTime();
    long lastThreadTime = newBean.getCurrentThreadCpuTime();

    while (true)
    {
        // Do something that takes at least 10ms (on windows)
        try
        {
            int j = 0;
            for (int i = 0; i < 20000000; i++)
                j = (j + i) * j / 2;
            Thread.sleep(100);
        }
        catch (InterruptedException e)
        {
        }

        // Calculate coarse CPU usage:
        long time = System.nanoTime();
        long threadTime = newBean.getCurrentThreadCpuTime();
        double load = (threadTime - lastThreadTime) / (double)(time - lastTime);
        System.out.println((float)load);

        // For next iteration.
        lastTime = time;
        lastThreadTime = threadTime;
    }

You need to use double precision because a long doesn't fit in a float (though it might work 99.9999999999999999% of the time)

If the 'something' you're doing takes less than approximately 1.6ms (Windows), then the returned value will not even have increased at all and you'll perpetually measure 0% CPU erroneously.

Because getCurrentThreadCpuTime is VERY inaccurate (with delays less than 100ms), smoothing it helps a lot:

    long lastTime = System.nanoTime();
    long lastThreadTime = newBean.getCurrentThreadCpuTime();

    float smoothLoad = 0;
    while (true)
    {
        // Do something that takes at least 10ms (on windows)
        try
        {
            int j = 0;
            for (int i = 0; i < 2000000; i++)
                j = (j + i) * j / 2;
            Thread.sleep(10);
        }
        catch (InterruptedException e)
        {
        }

        // Calculate coarse CPU usage:
        long time = System.nanoTime();
        long threadTime = newBean.getCurrentThreadCpuTime();
        double load = (threadTime - lastThreadTime) / (double)(time - lastTime);
        // Smooth it.
        smoothLoad += (load - smoothLoad) * 0.1; // damping factor, lower means less responsive, 1 means no smoothing.
        System.out.println(smoothLoad);

        // For next iteration.
        lastTime = time;
        lastThreadTime = threadTime;
    }

Comments

1

This is not possible using pure Java. See this article for some ideas.

Comments

1

Maybe if stuck, you might 'sense' cpu availability by running an intermittent bogomips calculator in a background thread, and smoothing and normalising its findings. ...worth a shot no :?

1 Comment

This is a reasonable idea. You'll have to use proper microbenchmark tricks though (run for some length of time, warm up all loops before timing, use System.nanoTime()). There will still be a fair bit of flutter in performance too over the timing interval.
0

if you are using linux - just use jconsole - you will get all the track of java memory management

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.