17

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

Raedwald
  • 46,613
  • 43
  • 151
  • 237
shamkovich
  • 171
  • 1
  • 1
  • 3

6 Answers6

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.

Community
  • 1
  • 1
strainer
  • 617
  • 9
  • 21
7

How about using jmx mbeans?

final OperatingSystemMXBean myOsBean= 
            ManagementFactory.getOperatingSystemMXBean();
double load = myOsBean.getSystemLoadAverage();
dm76
  • 4,130
  • 8
  • 35
  • 46
baskin
  • 1,643
  • 1
  • 18
  • 29
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;
    }
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
1

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

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
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 :?

strainer
  • 617
  • 9
  • 21
  • 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. – BobMcGee Jan 14 '10 at 06:25
0

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

Devendar
  • 323
  • 1
  • 4
  • 20