怎样在Java中得到CPU的使用情况呢?这儿同时有一个好消息和一个坏消息。 坏消息是不能使用纯Java的方法得到CPU的使用。没有这方面的直接的API。一个建议的替代方法是通过Runtime.exec()确定JVM的进程ID(PID),调用外部的、平台相关的命令,例如ps,然后在运行结果中解析出感兴趣的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 JNICALL Java_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls) 二、本地方法实现 在大多数的Win32平台上,该方法可以使用GetProcessTimes()系统调用实现,差不多仅需要3行代码就可以了: 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)); } 该方法首先累加用于执行当前进程的核心和用户代码耗费的时间,除以处理器的数目,并把结果转换到毫秒。fileTimeToInt64()是一个辅助函数,用于把FILETIME结构的数据转换为64位的整数。s_currentProcess 和 s_numberOfProcessors是全局变量,当JVM装载本地库时即初始化。 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; } 注意,如果你在UNIX平台上实现getProcessCPUTime(),你应该以getrusage系统调用开始。 三、调用本地方法 回到Java中,在SystemInformation类中,装载本地库(silib.dll on Win32)最好通过静态初始化代码块完成。 private static final String SILIB = "silib"; static { try { System.loadLibrary (SILIB); } 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使用信息,这儿的要点是现在我们可以以编程方式记录该信息。对于长时间运行测试和服务器应用诊断程序,会派上用场。
个人博客已经迁移到如下网站 萌萌的IT人, 后续所有的文章都会在此发布
----------------------------------------------------------------------------------
相关推荐
一般来说,JNI有点复杂。但是,如果你仅仅单向调用--从Java调用本地代码,并且仅使用基本型进行通讯--事情还是很简单的。本文介绍了在Java中声明JNI方法,给出了在Java应用程序中使用JNI来监视CPU的实例。
博文链接:https://huangpengxiao.iteye.com/blog/96670
java中RCP中使用JNI
本文档主要讲述的是Java本地调用JNI使用规范详解;JNI概述;JavaNative Interface的缩写,中文为Java本地调用。从Java1.1开始,JNI即成为Java标准的一部分。 JNI设计的目的是为了允许Java代码与其他语言进行交互。但...
[JAVA]使用JNI技术实现JAVA程序调用dll、[JAVA]使用JNI技术实现JAVA程序调用dll
Java中使用Jni简单示例过程.doc
1、 在Java程序中复用以前写过的C/C++代码。 2、 自己实现一个java虚拟机 3、 学习不同语言如何进行协作,尤其是如何实现垃圾回收和多线程。 4、 把一个虚拟机实现整合到用C/C++写的程序中。 本书是写给开发者的。...
由于JNI是JVM规范的一部分,因此可以将我们写的JNI的程序在任何实现了JNI规范的Java虚拟机中运行。同时,这个特性使我们可以复用以前用C/C++写的大量代码JNI是一种在Java虚拟机机制下的执行代码的标准机制。
java获得CPU序列号,java通过jni连接c语言,从C中获得CPU的序列号。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
java获得CPU、内存使用率,通过jni获得C程序获得CPU、内存的使用率,可直接运行。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这是一个简单的JNI开发中C层调用Java层函数的事例工程,对应的博客地址是:http://blog.csdn.net/hty1053240123/article/details/52126386
文档里描述了如何通过jni方法在java与c++代码之间传递非基本类型数据
JAVA使用JNI读写INI文件的实例。 JAVA本身并没有读写INI文件的现成方法,有些人自己编写方法来读写INI文件,但是这样的方法或多或少的存在着一些问题。此示例旨在利用本地的WIN32API函数来读写INI文件,这样可以保证...
在VS2013中使用JNI进行JAVA和C++之间的互调,这两个文件只是项目中的一部分,仅供参考
博文配套的JNI测试程序,测试Java调用C++的DLL库,详情见文章https://blog.csdn.net/xinxin_2011/article/details/85006113
最近没事,回忆起来原来学过的C++,想把java与C++结合起来,就想到JNI来研究一下,附件为源程序和步骤,供有兴趣的朋友参考.
利用JNI技术实现Java中调用C++编写的函数库示例程序源码,并附上参考JNI文档。 详情见本人博客:Java学习之通过JNI调用C/C++编写的dll链接库(图文教程)(http://write.blog.csdn.net/postlist)
java中NDK的使用,java Native Interface的使用技巧
world 文档,描述了Android g1环境,C、Java、JNI调用(C调Java、Java调C)基本运算、方法调用、字符串连接的效率测试结果。
由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)来执行。VM在Android平台里,扮演很重要的角色。 此外,在执行Java类的过程中,如果...