国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

在Java應用程序中使用JNI來監視CPU詳解

2019-11-17 05:56:27
字體:
來源:轉載
供稿:網友

怎樣在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使用信息,這兒的要點是現在我們可以以編程方式記錄該信息。對于長時間運行測試和服務器應用診斷程序,會派上用場。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 花垣县| 彭州市| 宣恩县| 卓资县| 寿光市| 峨边| 吉木萨尔县| 克山县| 泸西县| 鹰潭市| 稷山县| 儋州市| 龙泉市| 兴安盟| 栾城县| 图木舒克市| 上高县| 崇明县| 东港市| 南皮县| 衡阳市| 鄂托克前旗| 阿拉善左旗| 兴业县| 鄂尔多斯市| 油尖旺区| 鄂托克旗| 清新县| 云浮市| 仁化县| 汶川县| 甘孜县| 临高县| 太仓市| 依兰县| 梁河县| 延庆县| 南通市| 南京市| 读书| 嘉荫县|