How to get the CPU Usage from Java on Windows (by Thierry Janaudy)
 
        > May, 21st, 2005  
   


This article shows you how to get the current CPU usage from Java on Windows



Prerequisites >

• J2SE 1.4+ and JNI
• Win32 C


Intro >

The code is based on the Microsoft Platform SDK: Performance Monitoring, specifically PdhAddCounter and PdhOpenQuery.
The idea is to define a Java native function, and use the above functions to query the current CPU Usage, as part of a DLL.

We are going to use a tool that is part of the JDK, the javah

The Java class >

package com.jyperion.cpuusage;

/**
 * CPU
 * 
 * @author Thierry Janaudy
 */
public final class CPU {
  /**
   * INSTANCE
   */
  public static final CPU INSTANCE = new CPU();
	
  static {
    System.loadLibrary("CPUUSAGE");
  }
	
  /**
   * CPU
   */
  private CPU() {
  }
	
  /**
   * getCpuUsage
   * @return
   */
  public native int getCpuUsage();
	
  /**
   * main
   * @param _
   */
  public static void main(String _[]) throws Exception {
    while(true) {
      Thread.sleep(1000L);
      System.out.println("Current CPU Usage: " + CPU.INSTANCE.getCpuUsage());
    }
  }
}
		
Generate the C header >

Type javah -jni com.jyperion.cpuusage.CPU
This generates a file called com_jyperion_cpuusage_CPU.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_jyperion_cpuusage_CPU */

#ifndef _Included_com_jyperion_cpuusage_CPU
#define _Included_com_jyperion_cpuusage_CPU
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jyperion_cpuusage_CPU
 * Method:    getCpuUsage
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_jyperion_cpuusage_CPU_getCpuUsage
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
		
The C code for the DLL >

There are 3 main files: CpuPerf.h, CpuPerf.cpp and the DLL file CPUUSAGE.cpp.
CpuPerf.h
/**
 * CpuPerf.h class definition
 *
 * @author Thierry S Janaudy
 * @email janaudy@jyperion.com
 * @date 20 May 2005
 */

#ifndef __CPU_PERF__
#define __CPU_PERF__

#include 
#include 
#include 
using namespace std;

#define CPU_USAGE "\\Processor(_Total)\\% Processor Time"

typedef struct CounterStruct {
	LONG lValue;			// The current value of this counter
    HCOUNTER hCounter;      // Handle to the counter - given to use by PDH Library
} CounterStruct, *PCounterStruct;

class CpuPerf {
private:
	HQUERY hQuery;
	PCounterStruct pCounter;
	BOOL collectCPUData();

protected:

public:
	CpuPerf();
	~CpuPerf();
	BOOL init();
	long getCPUUsage();
};

#endif
		
CpuPerf.cpp
/**
 * CpuPerf.cpp class
 *
 * @author Thierry S Janaudy
 * @email janaudy@jyperion.com
 * @date 20 May 2005
 */

#include "CpuPerf.h"

/**
 * Constructor
 */
CpuPerf::CpuPerf() {
	cout << "CpuPerf()" << endl;
}

/**
 * Destructor
 */
CpuPerf::~CpuPerf() {
	PdhCloseQuery(&this->hQuery);
	cout << "~CpuPerf()" << endl;
}

/**
 * Init
 */
BOOL CpuPerf::init() {
	cout << "init()" << endl;

	if (PdhOpenQuery(NULL, 1, &this->hQuery) != ERROR_SUCCESS) {
		cout << "PdhOpenQuery() failed" << endl;
		return false;
	}
	else {
		this->pCounter = new CounterStruct;
		if (!pCounter) {
			cout << "new CounterStruct failed" << endl;
			return false;
		}
		
		// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/pdhaddcounter.asp
		if (PdhAddCounter(this->hQuery, CPU_USAGE, 
			(DWORD)this->pCounter, &(this->pCounter->hCounter)) != ERROR_SUCCESS) {
			cout << "PdhAddCounter() failed" << endl;
			delete pCounter;
			return false;
		}

		cout << "init() succeeded" << endl;
		return true;
	}
}

/**
 * Collects CPU data
 */
BOOL CpuPerf::collectCPUData() {
	if (PdhCollectQueryData(this->hQuery) != ERROR_SUCCESS) {
		cout << "PdhCollectQueryData() failed" << endl;
		return false;
	}
	else {
		cout << "PdhCollectQueryData() succeeded" << endl;
		PDH_FMT_COUNTERVALUE counterValue;
		if (PdhGetFormattedCounterValue(pCounter->hCounter, PDH_FMT_LONG, NULL, &counterValue) 
			  != ERROR_SUCCESS) {
			cout << "PdhGetFormattedCounterValue() failed" << endl;
			return false;
		}

		if (counterValue.CStatus != ERROR_SUCCESS)
			return false;
		
		this->pCounter->lValue = counterValue.longValue;

		cout << "collectCPUData CPU is " << this->pCounter->lValue << endl;

		return true;
	}
}
		
CPUUSAGE.cpp
/**
 * CpuPerf.cpp class
 *
 * @author Thierry S Janaudy
 * @email janaudy@jyperion.com
 * @date 20 May 2005
 */

#include "stdafx.h"
#include "CpuPerf.h"
#include "com_jyperion_cpuusage_CPU.h"

static CpuPerf cpu;
static BOOL init = false;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
	cout << "DLLMain" << endl;

	if (!init) {
		cpu = CpuPerf();
		init = cpu.init();
	}

    return true;
}

/**
 * Constructor
 */
CpuPerf::CpuPerf() {
	cout << "CpuPerf()" << endl;
}

/**
 * Destructor
 */
CpuPerf::~CpuPerf() {
	PdhCloseQuery(&this->hQuery);
	cout << "~CpuPerf()" << endl;
}

/**
 * Init
 */
BOOL CpuPerf::init() {
	cout << "init()" << endl;

	if (PdhOpenQuery(NULL, 1, &this->hQuery) != ERROR_SUCCESS) {
		cout << "PdhOpenQuery() failed" << endl;
		return false;
	}
	else {
		this->pCounter = new CounterStruct;
		if (!pCounter) {
			cout << "new CounterStruct failed" << endl;
			return false;
		}
		
		// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/pdhaddcounter.asp
		if (PdhAddCounter(this->hQuery, CPU_USAGE, 
			(DWORD)this->pCounter, &(this->pCounter->hCounter)) != ERROR_SUCCESS) {
			cout << "PdhAddCounter() failed" << endl;
			delete pCounter;
			return false;
		}

		cout << "init() succeeded" << endl;
		return true;
	}
}

/**
 * Collects CPU data
 */
BOOL CpuPerf::collectCPUData() {
	if (PdhCollectQueryData(this->hQuery) != ERROR_SUCCESS) {
		cout << "PdhCollectQueryData() failed" << endl;
		return false;
	}
	else {
		//cout << "PdhCollectQueryData() succeeded" << endl;
		PDH_FMT_COUNTERVALUE counterValue;
		if (PdhGetFormattedCounterValue(pCounter->hCounter, PDH_FMT_LONG, NULL, &counterValue) 
			  != ERROR_SUCCESS) {
			cout << "PdhGetFormattedCounterValue() failed" << endl;
			return false;
		}

		if (counterValue.CStatus != ERROR_SUCCESS)
			return false;
		
		this->pCounter->lValue = counterValue.longValue;

		//cout << "collectCPUData CPU is " << this->pCounter->lValue << endl;

		return true;
	}
}

/**
 * Returns the CPU usage
 */
long CpuPerf::getCPUUsage() {
	this->collectCPUData();
	return this->pCounter->lValue;
}

/*
 * Class:     com_jyperion_cpuusage_CPU
 * Method:    getCpuUsage
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_jyperion_cpuusage_CPU_getCpuUsage(JNIEnv *env, jobject jobj) {
	return cpu.getCPUUsage();
}
		
Download >
cpu-usage.zip

Author > Thierry Janaudy is a Technical Architect working for Jyperion Ltd.
Do not forget to check out our J2EE labs for jBoss