Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Profiling CPU usage from within a Java application

Roll your own CPU usage monitor using simple JNI

  • Print
  • Feedback

November 8, 2002

Q How do you determine CPU usage in Java?

A So, here is the good news and the bad news. The bad news is that programmatically querying for CPU usage is impossible using pure Java. There is simply no API for this. A suggested alternative might use Runtime.exec() to determine the JVM's process ID (PID), call an external, platform-specific command like ps, and parse its output for the PID of interest. But, this approach is fragile at best.

The good news, however, is that a reliable solution can be accomplished by stepping outside Java and writing a few C code lines that integrate with the Java application via Java Native Interface (JNI). I show below how easy it is by creating a simple JNI library for the Win32 platform. The Resources section contains a link to the library you can customize for your own needs and port to other platforms.

In general, JNI is somewhat complex to use. However, when you call in one direction only—from Java into native code—and communicate using primitive data types, things remain simple. There are many good references (see Resources) on JNI, so I do not provide a JNI tutorial here; I merely outline my implementation steps.

I begin by creating a class com.vladium.utils.SystemInformation that declares a native method, which returns the number of milliseconds of CPU time used by the current process so far:

         public static native long getProcessCPUTime ();


I use the javah tool from the JDK to produce the following C header for my future native implementation:

JNIEXPORT jlong JNICALL
Java_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls)


On most Win32 platforms, this method can be implemented using the GetProcessTimes() system call and is literally three lines of C code:

JNIEXPORT jlong JNICALL
Java_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls)
{
    FILETIME creationTime, exitTime, kernelTime, userTime;
    
    GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
    return (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) /
        (s_numberOfProcessors * 10000));
}


This method adds CPU time spent executing kernel and user code on behalf of the current process, normalizes it by the number of processors, and converts the result to milliseconds. The fileTimeToInt64() is a helper function that converts the FILETIME structure to a 64-bit integer, and s_currentProcess and s_numberOfProcessors are global variables that can be conveniently initialized in a JNI method that's called once when the JVM loads the native library:

static HANDLE s_currentProcess;
static int s_numberOfProcessors;
JNIEXPORT jint JNICALL
JNI_OnLoad (JavaVM * vm, void * reserved)
{
    SYSTEM_INFO systemInfo;
        
    s_currentProcess = GetCurrentProcess ();
    GetSystemInfo (& systemInfo);
    s_numberOfProcessors = systemInfo.dwNumberOfProcessors;
    return JNI_VERSION_1_2;
}


Note that if you implement getProcessCPUTime() on a Unix platform, you would likely use the getrusage system call as your starting point.

  • Print
  • Feedback

Resources