`
dyllove98
  • 浏览: 1414672 次
  • 性别: Icon_minigender_1
  • 来自: 济南
博客专栏
73a48ce3-d397-3b94-9f5d-49eb2ab017ab
Eclipse Rcp/R...
浏览量:39310
4322ac12-0ba9-3ac3-a3cf-b2f587fdfd3f
项目管理checkList...
浏览量:80479
4fb6ad91-52a6-307a-9e4f-816b4a7ce416
哲理故事与管理之道
浏览量:133573
社区版块
存档分类
最新评论

Java应用程序中使用JNI来监视CPU详解

阅读更多
怎样在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人后续所有的文章都会在此发布

 

 

----------------------------------------------------------------------------------

分享到:
评论
1 楼 mercyblitz 2010-06-29  
JMX就提供了这个功能,也是JNI实现的。

相关推荐

    在Java应用程序中使用JNI来监视CPU详解

    以上就是如何在Java中使用JNI来监视CPU的基本流程。在Unix平台上,实现`getProcessCPUTime()`时,应使用`getrusage`系统调用代替`GetProcessTimes()`。虽然JNI的使用可能较为复杂,但通过它,我们可以充分利用本地...

    java 通过jni查看windows的CPU利用率的问题

    标题“Java通过JNI查看Windows的CPU利用率的问题”涉及到的是Java编程语言如何利用Java Native Interface (JNI) 这一技术来获取Windows操作系统的CPU使用情况。JNI是Java平台标准的一部分,它允许Java代码和其他语言...

    java中RCP中使用JNI

    通过JNI,开发者可以在Java应用中嵌入C/C++代码,解决Java在某些场景下性能不足的问题,或者利用现有的本地库资源。 2. **在Java RCP中使用JNI的动机** - **性能优化**:对于需要高性能计算或者图形处理的任务,...

    Jni应用个人详解

    Jni应用详解 Jni(Java Native Interface)是一种allowing Java代码与 native 代码集成的技术,使得Java程序能够调用native方法和库。下面是Jni应用的详细解释: 一、Jni的主要作用 Jni的主要作用是让Java程序...

    Java中使用Jni简单示例过程

    ### Java与JNI交互详解:基于“Java中使用Jni简单示例过程”的深入解析 #### 核心概念:Java Native Interface (JNI) Java Native Interface(JNI)是Java平台标准的一部分,它允许Java代码与其他语言(如C或C++)...

    java(jni)获得CPU序列号

    通过上述步骤,我们了解了如何利用Java Native Interface (JNI)机制,结合C/C++编程来实现Java程序获取CPU序列号的功能。这一过程不仅展示了不同编程语言之间的交互方式,还涉及到了操作系统API的使用,为开发者提供...

    Java使用JNI测试程序

    Java使用JNI(Java Native Interface)测试程序是一种将Java与C++代码集成的技术,它允许Java应用程序直接调用本地(非Java)代码,如C++编写的动态链接库(DLL)。在本示例中,我们看到的是一个用于演示如何通过JNI...

    用jni获得cpu和内存使用率

    在本例中,我们探讨的是如何使用JNI来获取系统的CPU和内存使用率,这对于系统监控、性能分析或者资源管理类的应用来说是至关重要的。 首先,我们需要了解JNI的基本工作原理。JNI提供了一套接口,让Java代码可以调用...

    使用C++创建java虚拟机JVM,使用JNI调用java函数.zip

    在提供的资源"使用C++创建java虚拟机JVM,使用JNI调用java函数"中,可能详细介绍了以上步骤的实际应用,包括代码示例和可能遇到的问题及解决方案。通过学习和实践这个教程,开发者可以更好地理解和掌握C++与Java之间...

    GMSSL的java调用(JNI库和调用实例).zip

    在本例中,JNI将作为Java与C/C++编译的GMSSL库之间的桥梁,使得Java应用程序能够直接调用GMSSL中的原生函数。 1. **SM2算法**:这是一种非对称公钥加密算法,基于椭圆曲线密码学(ECC)。SM2不仅提供了公钥加密功能,...

    Java JNI调用IC卡读卡器

    通过以上步骤,你就可以在Java应用程序中利用JNI调用IC卡读卡器的DLL,实现读取和写入IC卡的功能。注意,调用DLL可能会涉及线程安全、错误处理以及资源管理等问题,所以在实际应用中需要仔细考虑这些因素。此外,...

    Java程序中JNI的编程指南

    总结来说,《Java程序中JNI的编程指南》是开发者深入理解和使用JNI的宝贵资源,它不仅提供了理论知识,还有丰富的实践指导,无论是对初学者还是经验丰富的开发者,都能从中受益匪浅。通过本书,读者可以学习到如何...

    java中使用JNI调用vs2005

    通过这个教程,你应该能够理解如何在Java中使用JNI调用VS2005编译的C++代码。这为Java应用程序提供了与本地系统资源深度集成的能力,比如利用C++库的高性能计算或者访问操作系统特定的功能。熟练掌握JNI技术,可以极...

    Delphi10.3 中通过JNI调用 Java 函数

    通过JNI,开发者可以在Java应用程序中调用C、C++甚至是其他语言编写的原生代码,反之亦然。在Delphi中调用Java函数,可以利用JNI提供的API来实现这一目标,从而扩展Delphi程序的功能。 首先,我们需要了解JNI的基本...

    Java本地调用JNI使用规范详解.doc

    Java本地调用JNI(Java Native Interface)是一种技术,允许Java代码与用其他编程语言(如C和C++)编写的代码进行交互。...正确理解和使用JNI的规范能确保Java代码与本地代码的无缝交互,同时保持程序的稳定性和效率。

    java调用C源程序(JNI)

    JNI是Java平台的一部分,它为Java应用程序提供了一种方式来调用本地方法(即非Java代码)。这些本地方法可以是C、C++或者其他本地语言编写的,从而使得Java可以充分利用现有的C/C++库。 2. **JNI工作原理** - **...

    java(jni)获得CPU、内存使用率 绝对可用

    本文将详细讲解如何通过JNI在Java中获取CPU和内存的使用率。 首先,我们需要理解CPU和内存使用率的基本概念。CPU使用率是指CPU在一段时间内执行非空闲任务的比例,通常以百分比表示。内存使用率则反映了系统分配给...

    JAVA中jni使用

    Java中的JNI(Java Native Interface)是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。JNI在很多场景下都是必要的,比如调用现有的C/C++库、提高性能的关键算法实现、或者利用硬件特性等。这篇...

    JNI使用规范详解.pdf

    由于JNI是JVM规范的一部分,因此可以将我们写的JNI的程序在任何实现了JNI规范的Java虚拟机中运行。同时,这个特性使我们可以复用以前用C/C++写的大量代码JNI是一种在Java虚拟机机制下的执行代码的标准机制。

    Android应用程序使用JNI调用驱动程序

    JNI允许Java应用程序与本地代码进行交互,包括操作系统内核、驱动程序等。本文将深入探讨如何利用Android NDK(Native Development Kit)在应用程序中使用JNI调用驱动程序。 首先,我们需要了解NDK的基本概念。NDK...

Global site tag (gtag.js) - Google Analytics