论坛登陆 用户名:  密 码:
设为首页  加入收藏
08年北京名校秋季招生
名牌院校免试入学宽进严出,突破考分限制,名校与你零距离,以下院校按报名先后顺序录取,24小时网上报名覆盖全国
  您现在的位置: 中国教育招生在线 >> IT >> JAVA认证 >> IT正文
怎样在Java应用程序中监视CPU的使用状况
 作者:佚名     2007-3-14 16:34:47        来源:不详  浏览次数:

 

 

 

 

 

 

 

 

怎样在Java中得到CPU的使用情况呢?这儿同时有一个好消息和一个坏消息。坏消息是不能使用纯Java的方法得到CPU的使用。没有这方面的直接的API。一个建议的替代方法是通过Runtime.exec()确定JVM的进程ID(PID),调用外部的、平台相关的命令,然后在运行结果中解析出感兴趣的PID。但是,这种方法并不理想。

好消息是,可以采用一个更为可靠的方案:跳出Java,写几行C代码,然后通过JNI进行整合。下面我将向你展示编写一个Win32平台的简单的JNI库是多么简单。

一般来说,JNI有点复杂。但是,如果你仅仅单向调用--从Java调用本地代码,并且仅使用基本型进行通讯--事情还是很简单的。有许多JNI方面的学习资料,所以这儿我就不介绍JNI的基础了。我仅介绍我的实现步骤。

一、在Java中声明JNI方法

开始,我创建一个声明了本地方法的类com.vladium.utils.SystemInformation,该方法返回当前进程已使用的CPU的毫秒数。

public staticnative long getProcessCPUTime();

使用JDK内置的javah工具产生将来本地代码实现使用的C头文件。

JNIEXPORT jlong 
JNICALLJava_com_vladium_utils_
SystemInformation_getProcessCPUTime
(JNIEnv * env, jclass cls)

二、本地方法实现

在大多数的Win32平台上,该方法可以使用GetProcessTimes()系统调用实现,差不多仅需要3行代码就可以了:

JNIEXPORT jlong 
JNICALLJava_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));
}

该方法首先累加用于执行当前进程的核心和用户代码耗费的时间,除以处理器的数目,并把结果转换到毫秒。fileTimeToInt64()是一个辅助函数,用于把FILETIME结构的数据转换为64位的整数。s_currentProcess 和 s_numberOfProcessors是全局变量,当JVM装载本地库时即初始化。

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

注意,如果你在UNIX平台上实现getProcessCPUTime(),你应该以getrusage系统调用开始。

三、调用本地方法

回到Java中,在SystemInformation类中,装载本地库(silib.dll on Win32)最好通过静态初始化代码块完成。

private static final 
String SILIB = "silib"; 
static 
{
try 
{
System.loadLibrary (SILI;
} 
catch (UnsatisfiedLinkError e) 
{
System.out.println 
("native lib '" + SILIB + "'
not found in 'java.library.path':
" + System.getProperty
("java.library.path"));
throw e; // re-throw 
}
}

注意,getProcessCPUTime()返回自JVM进程创建以来使用的CPU时间。就这个数据本身而言,对于这儿并没有太多的用处。我需要更有用的Java方法来记录不同的时刻的数据快照(data snapshots),并报告任何两个时间点之间CPU的使用。

public static final class
CPUUsageSnapshot
{
private CPUUsageSnapshot 
(long time, long CPUTime)
{
m_time = time; 
m_CPUTime = CPUTime;
} 
public final long m_time, m_CPUTime; 
}
// end of nested class public
static CPUUsageSnapshot 
makeCPUUsageSnapshot ()
{ 
return new CPUUsageSnapshot
(System.currentTimeMillis (), 
getProcessCPUTime ()); 
} 
public static double 
getProcessCPUUsage 
(CPUUsageSnapshot start, 
CPUUsageSnapshot end)
{ return ((double)(end.m_CPUTime 
- start.m_CPUTime)) / 
(end.m_time - start.m_time);
}

四、一个简单的CPU监视程序

“CPU监视API”基本就完成了!最后,我创建了一个singleton的线程类CPUUsageThread,它自动地每过一个时间间隔(默认是0.5秒)就拍下一个数据快照,并报告给所有的CPU使用事件的监听者(Observer模式)。

public void run ()
{ 
while (! isInterrupted ())
{ 
final SystemInformation.
CPUUsageSnapshot snapshot 
= SystemInformation.makeCPUUsageSnapshot ();
notifyListeners (snapshot); 
try { sleep (sleepTime);
}
catch (InterruptedException e)
{ 
return;
}
} 
}

CPUmon类是一个示例的监听器,仅简单地把CPU的使用情况打印输出到System.out。

public static void 
main (String [] args) throws Exception
{ 
if (args.length == 0) 
throw new IllegalArgumentException
("usage: CPUmon
<app_main_class> <app_main_args...>");
CPUUsageThread monitor
= CPUUsageThread.getCPUThreadUsageThread ();
CPUmon _this = new CPUmon ();
Class app = Class.forName (args [0]);
Method appmain = app.getMethod
("main", new Class [] {String[].class});
String [] appargs 
= new String [args.length - 1]; 
System.arraycopy 
(args, 1, appargs, 0, appargs.length);
monitor.addUsageEventListener (_this);
monitor.start (); appmain.invoke
(null, new Object [] {appargs});
}

另外,为了能够在启动要监视的应用程序之前开始CPUUsageThread,CPUmon.main()包装了另一个Java主类。

作为演示,我运行CPUmon和JDK1.3.1的SwingSet2示例程序(不要忘了把silib.dll安装到OS的PATH环境变量或者java.library.path系统属性所覆盖的路径下):

>java -Djava.library.path=
. -cp silib.jar;
(my JDK install dir)\demo\jfc
\SwingSet2\SwingSet2.jar CPUmon SwingSet2

[PID: 339] CPU usage: 46.8%
[PID: 339] CPU usage: 51.4%
[PID: 339] CPU usage: 54.8%
(while loading, the demo
uses nearly 100% of one of
the two CPUs on my machine)
...
[PID: 339] CPU usage: 46.8%
[PID: 339] CPU usage: 0%
[PID: 339] CPU usage: 0%
(the demo finished loading 
all of its panels and is mostly idle)
...
[PID: 339] CPU usage: 100%
[PID: 339] CPU usage: 98.4%
[PID: 339] CPU usage: 97%
(I switched to the ColorChooserDemo
panel which ran a CPU-intensive
animation that used both of my CPUs)
...
[PID: 339] CPU usage: 81.4%
[PID: 339] CPU usage: 50%
[PID: 339] CPU usage: 50%
(I used Windows NT Task Manager
to adjust the CPU affinity for the
"java" process to use a single CPU)
...

当然,我也可以通过任务管理器查看到CPU使用信息,这儿的要点是现在我们可以以编程方式记录该信息。对于长时间运行测试和服务器应用诊断程序,应该会派上用场。

(T117)


责任编辑:lss
  相关新闻
怎样学习C语言
CCIE是怎样炼成的—我到北京考试的经历
Java基础-漫谈EJB在Java中的应用
漫谈EJB在Java中的应用(二)
J2EE技术-漫谈EJB在Java中的应用
怎样才能阻止用户打开加密信息?
把您从麻烦中解脱的JNDI在J2EE中的角色
第三方类库:在Java中读写Excel文件
怎样配置具有SSL保护的FTP服务器
在Java中应用设计模式-Factory Method
怎样学习C语言
CCIE是怎样炼成的—我到北京考试的经历
Java基础-漫谈EJB在Java中的应用
漫谈EJB在Java中的应用(二)
在Java中监控文本框的变化
第三方类库:在Java中读写Excel文件
在JSE环境中使用Hibernate EntityManger
在JSE环境中使用Hibernate EntityManger
使用JWSDP完成Web Service在java的入门
教您怎样部署基于WebSphere的J2EE应用
  评论
现在有100人对本文发表评论
查看所有评论
 
推  荐
 
100本成功必读热销书
热门招生
  北京文理研修学院   前进大学
  北京明园大学   北京建设大学
  北京邮电大学世纪学院   北方工商管理学院
  联想软件定向委培班   香港数码动画学院
  青年企业管理研修学院   北京华夏管理学院
热门培训
网络化办公专家培训认证 电子科技大学软件学院
软件测试工程师培训认证 北大青鸟十大授权培训
IT硬件工程师培训认证班 北京环球雅思荷兰预科
JAVA开发工程师培训 潜能时代IT服务管理培训
网络信息化工程师培训 清华大学继续教育学院
论坛精选
 
有些细节是男人也该注意的风度!最容易读错的字
某强人手机里保存的30条短信 中国十大高薪职业
最感人的十大韩剧经典台词 嫁给工程师的N个理由
爆强!只有一句话的鬼故事 转贴教你如何做妖精
 女人一定要記住的話 女人最好别嫁给最爱的男人
城市联盟
 大连 上海 天津 广州 西安 深圳  天津  青岛  大连  福州  沈阳  青海  连云港  南京  吉林  厦门  威海  辽宁  呼和浩特
Copyright © 2006   www.edu999.com   All rights reserved. 中国教育招生在线  版权所有
北京市通信管理局[2004]字第552号函    京ICP证040442号