利用Java配合BCB 4.0製作CPU特徵偵測器 |
|
conundrum
尊榮會員 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
利用Java配合BCB 4.0製作CPU特徵偵測器
http://edu.uuu.com.tw/article/010307b.htm
利用Java配合BCB 4.0製作CPU特徵偵測器
作者: 恆逸資訊 王森
筆者最近從事一個利用Java來發展密碼模組的工作,由於利用純Java語言所製作出來的密碼模組效率實在不好,最後我們把腦筋動到JNI(Java Native Interface)上. 為何會想到使用JNI呢? 大家應該都知道Java程式的執行必須透過Java Virtual Machine,透過一層仲介的結果,執行的效率必然比C/C++所編譯出來的原生碼(native code,即專屬各處理器的指令集)還要慢. 事實上,在JDK內附的java.math 這個package裡頭,許多部分也都應用了JNI來加快運算速度(例如Big Integer運算)。 硬體優勢
一旦利用的JNI,代表我們將能夠連結C/C++或是Assembly所撰寫的加密模組. 為了加快密碼模組的performance,必須運用一些硬體上的優勢,例如說當處理區塊加密運算時,如果能運用一點並行處理的觀念,就能夠適當地加快運算速度. 以目前的PC上的處理器來說,支援平行處理能力的技術就屬大家所熟知的MMX, Streaming SIMD Extension(大家也許比較熟悉的是KNI這個名詞),以及3DNOW!. 這些技術其實就是實做了SIMD(Single-Instruction, Multiple-Data)的概念,允許處理器在同一時間之內,使用單一指令,就可以同時處理好幾組資料。
另外,在Pentium等級以上的CPU具有利用Pipeline來加快執行速度的能力,只要調整Assembly code的排列順序,使其符合Intel Scheduling Rules,就可以充分利用CPU裡頭的U-pipe與V-pipe,加快執行速度. 其實,就筆者所使用的Visual C++ 6.0與Borland C++ Builder 4.0來說,雖然都有編譯器指令可以針對處理器做最佳化,但是如果您親自去看看編譯出來的結果,能然有很多地方無法盡如人意,因此如果遇到time critical的部分,仍然常常需要我們親自去調校以改善performance。
準備工作及注意事項
Ok,講到這邊,似乎離主題有點遠了,讓我們回歸正題吧! 為了讓我們可以在執行時期動態地依照CPU的能力來執行最佳化的程式碼,首要的工作就是要寫一些函式來偵測CPU的特性,於是筆者選擇了JDK 1.2以及BCB 4.0來完成整個由
Java code ---> JNI ---> Platform native code
的完整測試程式,如果以圖片來表示就如下圖:
準備工作及注意事項
Ok,講到這邊,似乎離主題有點遠了,讓我們回歸正題吧! 為了讓我們可以在執行時期動態地依照CPU的能力來執行最佳化的程式碼,首要的工作就是要寫一些函式來偵測CPU的特性,於是筆者選擇了JDK 1.2以及BCB 4.0來完成整個由
Java code ---> JNI ---> Platform native code
的完整測試程式,如果以圖片來表示就如下圖:
如果您抓取了筆者提供的原始碼,應該可以看到下面三個分別由Java與C++撰寫的程式模組:
CPUTestDll.bpr CPUTestDll.cpp
實做偵測CPU特性相關函式的模組
此為BCB 4.0之 專案檔,使用Project/make cputest的指令後,所產生的結果cputest.dll,是我們所要的。
編譯注意事項 : 由於在CPUTestDll.cpp裡頭我們用到組合語言指令CPUID,所以請打開Project/Option裡頭的Advanced Compiler次頁,裡頭有一個叫Instruction Set的地方,請勾選Pentium,否則編譯器會因為不支援此指令而產生編譯錯誤.如果您要把編譯過的結果給別人使用,建議您將Project/Option/Package次頁中的Build with Run-time Package選項 以及 Linker次頁中的Use Dynamic RTL選項通通取消掉。
請打開Project/Option/Directories Conditionals次頁,將JDK所在目錄\include 與JDK所在目錄\include\win32加到Include path裡頭 ; 另外也在Library Path中加入 JDK所在目錄\lib,否則會造成編譯錯誤。 CPUTest.java
這個Java程式是作為其他Java程式透過JNI以呼叫CPUTestDll.dll的介面. 筆者把 這個介面宣告於my.cpu這個package底下。
編譯注意事項 :
編譯Java程式時,請設定環境變數PATH與CLASSPATH 例如JDK安裝在C:\JDK1.2這個目錄,而此檔案放在c:\jdk1.2\my之下, 那麼請在提示符號下命令 PATH c:\jdk1.2\bin set CLASSPATH=C:\jdk1.2\classes;c:\JDK1.2\my test.java
這個Java程式將利用CPUTest物件當作介面,來呼叫實做於CPUTestDll.dll內的CPU 特徵偵測函數。
編譯注意事項 :
除了2的注意事項外,請將CPUTest.java放到 < JDK安裝目錄 >\classes\my\cpu這個 目錄之中,否則編譯將無法通過。 參考文件
JDK 1.2 on-line document
Intel Architecture Optimization/Reference manual Order Number: 245127-001
AMD 3DNOW! Technology Manua
用JDK 實做JNI介面
首先,為了讓所有的Java Code都可以使用我們的CPU特徵偵測函數,我們首先必須先製作一個介面類別:
■ 檔案列表CPUTest.java
/********************************************************************* CPUTest.java JNI 介面物件 1999 April 20 by 王森 *********************************************************************/ //加入my.cpu這個package之中 package my.cpu ; public class CPUTest { /*以下定義每種處理器所代表的常數*/ static public final int i386 = 0 ; //不支援CPUID的處理器(可辨識) static public final int Pentium = 1 ; //最早期的Pentium處理器(可辨識) static public final int Pentium_M = 2 ; //Pentium with MMX 處理器(可辨識) static public final int Pentium_2 = 3 ; //Pentium II 處理器(可辨識) static public final int Pentium_3 = 4 ; //Pentium III處理器(可辨識) static public final int Pentium_P = 5 ; //Pentium Pro 處理器(可辨識) static public final int K6 = 11 ; //同Pentium with MMX static public final int K6_2 = 12 ; //K6-2處理器((可辨識) static public final int K6_3 = 13 ; //同K6-2 /*以下定義所有會藉由JNI來叫用的函式*/ // 測試CPU是否支援CPUID指令,如果支援則傳回true,否則傳回false public native boolean CheckCPUID() ; ^^^^^^ 注意,所有的JNI函式都必須在函式宣告裡加上native這個修飾字 //辨識處理器是否支援MMX,如果支援則傳回true,否則傳回false public native boolean CheckMMX() ; //辨識處理器是否支援Stream SIMD Extension(即KNI),如果支援則傳回true,否則傳回false public native boolean CheckSSIMD() ; //辨識處理器是否支援AMD 3DNow,如果支援則傳回true,否則傳回false public native boolean Check3DNOW() ; //辨識CPU的等級,並傳回一個整數代表CPU的等級 public native int CheckCPUTYPE() ; //印出CPU的相關資訊 public native void PrintCPUInfo() ; note: 使用此函數之前,請先呼叫前面的所有函式, 因為前面的函式,除了傳回真偽之外,也會設定DLL檔之中的全域變數 而PrintCPUInfo會利用這些全域變數來做判定的工作 static { 我們把實做CPU偵測函式的模組做成DLL(動態連結函式庫)檔, 取名叫CPUDTestDll.dll,所以在這裡要載入此DLL } }接著我們在提示符號下使用指令 javac CPUTest.java 編譯此檔案,會產生CPUTest.class這個檔案. 然後我們把這兩個檔案都移至 < JDK安裝目錄 >/classes/my/cpu/ 這個目錄底下,如果沒有做此動作,恐怕下面的步驟都會遇到一些錯誤. 最後一個步驟,就是必須產生一個引入檔(Include file),我們將會在編譯CPUTestDll.dll實用到這個引入檔. 在提示符號下使用指令 javah my.cpu.CPUTest 就會在您目前的工作目錄下看到 my_cpu_CPUTest.h 到此為止,我們已經完成了第一個階段 ■ 檔案列表my_cpu_CPUTest.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class my_cpu_CPUTest */ #ifndef _Included_my_cpu_CPUTest #define _Included_my_cpu_CPUTest #ifdef __cplusplus extern "C" { #endif #undef my_cpu_CPUTest_i386 #define my_cpu_CPUTest_i386 0L #undef my_cpu_CPUTest_Pentium #define my_cpu_CPUTest_Pentium 1L #undef my_cpu_CPUTest_Pentium_M #define my_cpu_CPUTest_Pentium_M 2L #undef my_cpu_CPUTest_Pentium_2 #define my_cpu_CPUTest_Pentium_2 3L #undef my_cpu_CPUTest_Pentium_3 #define my_cpu_CPUTest_Pentium_3 4L #undef my_cpu_CPUTest_Pentium_P #define my_cpu_CPUTest_Pentium_P 5L #undef my_cpu_CPUTest_K6 #define my_cpu_CPUTest_K6 11L #undef my_cpu_CPUTest_K6_2 #define my_cpu_CPUTest_K6_2 12L #undef my_cpu_CPUTest_K6_3 #define my_cpu_CPUTest_K6_3 13L /* * Class: my_cpu_CPUTest * Method: Check3DNOW * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_Check3DNOW (JNIEnv *, jobject); /* * Class: my_cpu_CPUTest * Method: CheckCPUID * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckCPUID (JNIEnv *, jobject); /* * Class: my_cpu_CPUTest * Method: CheckCPUTYPE * Signature: ()I */ JNIEXPORT jint JNICALL Java_my_cpu_CPUTest_CheckCPUTYPE (JNIEnv *, jobject); /* * Class: my_cpu_CPUTest * Method: CheckMMX * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckMMX (JNIEnv *, jobject); /* * Class: my_cpu_CPUTest * Method: CheckSSIMD * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckSSIMD (JNIEnv *, jobject); /* * Class: my_cpu_CPUTest * Method: PrintCPUInfo * Signature: ()V */ JNIEXPORT void JNICALL Java_my_cpu_CPUTest_PrintCPUInfo (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif附帶一提,上面這個檔案完全是使用javah這個JDK內附的程式所產生,我們不要去修改它,以免發生更多意想不到的麻煩 C Builder 4.0實做native端 好,完成了介面部分,接下來就要開始實做部分啦! 首先,請先打開您的BCB 4.0,選擇 File/New裡頭的New次頁中,選擇開啟一個DLL專案檔. 開啟成功後,請將此專案的檔名取名為 CPUTestDll. 您就會在目錄下看到CPUTestDll.bpr與CPUTestDll.cpp兩個檔案,另外,為了讓編譯工作順利,您必須再調校一些編譯器選項,請參照前面準備工作及注意事項. 首先,請在CPUTestDll.cpp裡頭將my_cpu_CPUTest.h這個檔案引入 #include "my_cpu_CPUTest.h" 否則會產生"Undefined Symbol xxxx"的錯誤 完整程式碼如下: ■ 檔案列表CPUTestDll.cpp #include #pragma hdrstop #include #include "my_cpu_CPUTest.h" /*底下定義一些代表CPU的變數 */ const int i386 = 0 ; //不支援CPUID的處理器(可辨識) const int Pentium = 1 ; //最早期的Pentium處理器(可辨識) const int Pentium_M = 2 ; //Pentium with MMX 處理器(可辨識) const int Pentium_2 = 3 ; //Pentium II 處理器(可辨識) const int Pentium_3 = 4 ; //Pentium III處理器(可辨識) const int Pentium_P = 5 ; //Pentium Pro 處理器(可辨識) const int K6 = 11 ; //同Pentium with MMX const int K6_2 = 12 ; //K6-2處理器((可辨識) const int K6_3 = 13 ; //同K6-2 /***************************************************************************/ /*以下定義一些辨識CPU能力的變數 */ bool CPUID_S = false ; //測試是否支援CPUID指令 bool MMX = false ; //測試是否支援MMX bool SSIMD = false ; //測試是否支援Streaming SIMD Extension bool _3DNOW = false ; //測試是否支援3D!NOW int CPUTYPE = i386 ; //CPU的型態,初始值為i386 /***************************************************************************/下面我們將開始介紹這些原生函式的實做方式,但是有些觀念我們必須要先知道. 首先,在下面的函式裡頭,我們利用BCB內嵌組合語言來實做,雖然我們也可以利用Win32 API或其他方法來取得系統資訊和硬體資訊,可是就複雜度來說,實在不如用組合語言來的那麼簡潔.(網路上常有人在爭論組合語言跟高階語言的優劣,甚至認為組合語言已經沒有存在的必要,不過筆者還是覺得做什麼事就用最適合的語言會比較好)。 第二,在這些inline assembly code裡面,我們大量地利用了CPUID這個組合語言指令.這是一個辨識CPU相當好用的指令,除了辨識一些CPU的特殊能力,也可以提供一些廠方資訊.大家可以翻閱Intel的Instruction set reference來看看這個指令的用法.不過呢,這個指令只有在Pentium等級CPU中才提供,換句話說,486,386上這個指令應該無效,嚴格地說來,即使執行檔在486以下的電腦執行這段程式,應該是沒有問題才對. 可是大家應該還記得去年在Intel的CPU中一些don't care的指令集竟然會造成電腦當機的錯誤吧! 所以我想在使用這個指令以前,應該先看看CPU是否支援這個指令,如果不支援,就不要再做下去,以免發生不可預期的錯誤. 因此我們在使用CheckMMX, CheckSSIMD, Check3DNOW,這些函式以前,請務必先執行CheckCPUID這個函式.這個函式會去變更全域變數CPUID_S,因此不論是CheckMMX, CheckSSIMD, Check3DNOW,都會在使用CPUID指令前先檢查這個全域變數,如果是false,就不再繼續動作下去,以免發生非預期的錯誤。 最後一點,就是當C Builder在編譯內嵌組和語言的程式碼時,會在程式目錄中產生CPUTestDll.asm這個中間檔,請將Project/Option裡頭的Advanced Compiler次頁,裡頭有一個叫Instruction Set的地方,請勾選Pentium,否則不管您勾選386或是486,編譯器會因為不支援此指令而產生組譯錯誤。 /*以下開始實做所有的JNI函式*/ /*辨識處理器是否支援AMD 3DNow*/ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_Check3DNOW(JNIEnv *J, jobject O) { //如果不支援CPUID指令,就不必再做下去以免發生錯誤 if( CPUID_S == false ) return false; unsigned long temp ; asm mov eax,80000001h ; asm cpuid ; asm mov temp,edx ; //第31個bit為3D!NOW的特徵值 if ( temp & 0x80000000 ) { _3DNOW = true ; return true ; } return false; } /*測試CPU是否支援CPUID指令*/ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckCPUID(JNIEnv *J, jobject O) { //以下程式用來測試CPU是否支援CPUID指令 unsigned int A,B ; asm pushfd ; asm pop eax ; asm mov ebx,eax ; asm xor eax,00200000h ; asm push eax ; asm popfd ; asm pushfd ; asm pop eax ; asm mov A,eax ; asm mov B,ebx ; if ( A != B ) { CPUID_S = true ; return true ; } return false ; } /*辨識CPU的等級*/ JNIEXPORT jint JNICALL Java_my_cpu_CPUTest_CheckCPUTYPE(JNIEnv *J, jobject O) { //如果不支援CPUID指令,就不必再做下去以免發生錯誤 if( CPUID_S == false ) return i386 ; unsigned int temp ; asm mov eax,0 ; asm cpuid ; asm mov temp,eax ; if (temp == 2)//這是P6家族的情形 { CPUTYPE = Pentium_P ; //P6家族的第一顆processor為Pentium Pro if (SSIMD) //P6然後又支援SSIMD ..一定是Pentium III { CPUTYPE = Pentium_3 ; return Pentium_3 ; } if (MMX) //否則P6然後又支援MMX ..一定是Pentium II { CPUTYPE = Pentium_2 ; if( _3DNOW ) /支援MMX又支援3D!NOW,一定是K6-2 { CPUTYPE = K6_2 ; return K6_2 ; } return Pentium_2 ; } //如果都沒有支援以上這些多媒體指令集,那麼應該是 Pentium Pro了 return Pentium_P ; } if (temp == 1)//這是P5家族的情形 { CPUTYPE = Pentium ; //P5家族的第一顆processor為Pentium if (MMX) //P5然後又支援MMX ..一定是Pentium with MMX { CPUTYPE = Pentium_M ; return Pentium_M ; } return Pentium ; } return i386 ; } /*辨識處理器是否支援MMX*/ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckMMX(JNIEnv *J, jobject O) { //如果不支援CPUID指令,就不必再做下去以免發生錯誤 if( CPUID_S == false ) return false ; unsigned long temp ; asm mov eax,1 ; asm cpuid ; asm mov temp,edx ; //第23個bit為MMX的特徵值 //p.s bit的編號由0 ~ 31 if ( temp & 0x00800000 ) { MMX = true ; return true ; } return false ; } /*辨識處理器是否支援Stream SIMD Extension(即KNI) */ JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckSSIMD(JNIEnv *J, jobject O) { //如果不支援CPUID指令,就不必再做下去以免發生錯誤 if( CPUID_S == false ) return false ; unsigned long temp ; asm mov eax,1 ; asm cpuid ; asm mov temp,edx ; //第25個bit為Streaming SIMD Extension的特徵位元 //p.s bit的編號由0 ~ 31 if ( temp & 0x02000000 ) { SSIMD = true ; return true ; } return false ; } /*印出CPU的相關資訊*/ JNIEXPORT void JNICALL Java_my_cpu_CPUTest_PrintCPUInfo(JNIEnv *J, jobject O) { cout << "... Verify Some Processor Information ..." << endl ; cout << "The Capacity of your Processor : " << endl ; if ( MMX ) { cout << "Support Intel MMX Technology" << endl ; }else { cout << "No Intel MMX Technology Support" << endl ; } if ( SSIMD ) { cout << "Support Intel Streaming SIMD Extensions" << endl ; }else { cout << "No Intel Streaming SIMD Extensions Support" << endl ; } if ( _3DNOW ) { cout << "Support AMD 3D!NOW Technology" << endl ; }else { cout << "No AMD 3D!NOW Technology Support" << endl ; } cout << "CPU Type :" ; switch( CPUTYPE ) { case i386 : cout << "General i386 Processor" << endl ; break ; case Pentium : cout << "Intel Pentium Processor" << endl ; break ; case Pentium_M : cout << "Intel Pentium with MMX Processor" << endl ; break ; case Pentium_2 : cout << "Intel Pentium II Processor" << endl ; break ; case Pentium_3 : cout << "Intel Pentium III Processor" << endl ; break ; case Pentium_P : cout << "Intel Pentium Pro Processor" << endl ; break ; case K6 : cout << "AMD K6 Processor" << endl ; break ; case K6_2 : cout << "AMD K6 II Processor" << endl ; break ; case K6_3 : cout << "AMD K6 III Processor" << endl ; break ; } cout << "... Verify End ..." << endl ; } int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) { return 1; } //---------------------------------------------------------------------------大家可能會發現每個函式在回傳布林值以前,都會先去設定一個DLL內部的全域變數,這是因為效率的考量,假如讀者有興趣擴充筆者的程式,讓Java程式可以因為CPU的特徵去呼叫適當的函式,一旦你遇到兩次這種情形,您就必須呼叫CheckXXXX函式兩次,十次這種情形,您就要呼叫十次,相當地沒有效率,如果照筆者的實做法,只要呼叫一次,就會去設定紀錄CPU特徵的全域變數,接下來就不必再次呼叫CheckXXXX,直接存取全域變數就可以了. 大家可以參考一下PrintCPUInfo函式,大致上可以知道為何筆者這樣做的理由. 還有就是CheckCPUTYPE這個函式的方法並非是最正規的方法,筆者只是假設市面上只有AMD與Intel兩家廠商而已,如果要正確的辨認出廠商跟型號,我們還必須利用CPUID取得更多資訊才行,這就當作給諸位讀者一個練習的機會,相信只要讀者有心,去找找各種CPU的System Programming Manual,一定可以找到正確的偵測方法. 測試 終於到了要測試咱們程式正確性的時候了,所以我們撰寫了test.java ■ 檔案列表test.java import my.cpu. * ; class test { /*以下定義每種處理器所代表的常數*/ static public final int i386 = 0 ; //不支援CPUID的處理器(可辨識) static public final int Pentium = 1 ; //最早期的Pentium處理器(可辨識) static public final int Pentium_M = 2 ; //Pentium with MMX 處理器(可辨識) static public final int Pentium_2 = 3 ; //Pentium II 處理器(可辨識) static public final int Pentium_3 = 4 ; //Pentium III處理器(可辨識) static public final int Pentium_P = 5 ; //Pentium Pro 處理器(可辨識) static public final int K6 = 11 ; //同Pentium with MMX static public final int K6_2 = 12 ; //K6-2處理器((可辨識) static public final int K6_3 = 13 ; //同K6-2 //主程式開始 public static void main(String args[]) { boolean temp ; //取得JNI介面物件 CPUTest my = new CPUTest() ; //開始CPU相關資訊的初始化工作 temp = my.CheckCPUID() ; if( temp ) { System.out.println("CPUID support") ; } else { System.out.println("CPUID not support") ; } temp = my.CheckMMX() ; if( temp ) { System.out.println("MMX support") ; }else { System.out.println("MMX not support") ; } temp = my.CheckSSIMD() ; if( temp ) { System.out.println("SSIMD support") ; }else { System.out.println("SSIMD not support") ; } temp = my.Check3DNOW() ; if( temp ) { System.out.println("3DNOW support") ; }else { System.out.println("3DNOW not support") ; } System.out.println("") ; System.out.println("---------Starting Java code Print--------") ; switch(my.CheckCPUTYPE()) { case i386: System.out.println("i386") ; break ; case Pentium: System.out.println("Pentium") ; break ; case Pentium_M: System.out.println("Pentium with MMX") ; break ; case Pentium_2: System.out.println("Pentium II") ; break ; case Pentium_3: System.out.println("Pentium III") ; break ; case Pentium_P: System.out.println("Pentium Pro") ; break ; case K6: System.out.println("K6") ; break ; case K6_2: System.out.println("k6-2") ; break ; case K6_3: System.out.println("K6-3") ; break ; } System.out.println("") ; System.out.println("---------Starting native code Print--------") ; my.PrintCPUInfo() ; }//end of main }//end of class在命令列下打入javac test.java,就可以產生test.class這個檔案.接者請打java test來執行程式,不過首先您會先遇到下面的錯誤訊息: C:\jdk1.2\my>java test Exception in thread "main" java.lang.UnsatisfiedLinkError: no CPUTestDll in java .library.path at java.lang.ClassLoader.loadLibrary(Compiled Code) at java.lang.Runtime.loadLibrary0(Runtime.java:470) at java.lang.System.loadLibrary(System.java:745) at my.cpu.CPUTest.(CPUTest.java:48)這是什麼原因呢? 原來是因為Java Virtual Machine找不到CPUTestDll.dll,所以產生了執行時期例外.解決這個問題的方法有兩種: 第一種就是把CPUTestDll.dll拷貝到跟test.class同一個目錄下. 第二種方法就是下指令java -Djava.library.path=< DLL所在位置 > test,例如: java -Djava.library.path=c:\jdk1.2\my\dll test代表CPUTestDll.dll是放置在c:\jdk1.2\my\dll底下. 不論您用哪種方法,都可以看到下面的輸出結果: C:\jdk1.2\my>java test CPUID support MMX support SSIMD not support 3DNOW not support ---------Starting Java code Print-------- Pentium II ---------Starting native code Print-------- ... Verify Some Processor Information ... The Capacity of your Processor : Support Intel MMX Technology No Intel Streaming SIMD Extensions Support No AMD 3D!NOW Technology Support CPU Type :Intel Pentium II Processor ... Verify End ...以上是在筆者電腦上的執行情形.您的電腦上也成功地輸出結果了嗎? 結語 其實在本文章中,只應用了JNI幫我們傳遞一些參數給動態連結函式庫,再由動態連結函式庫傳回一些值給我們而已. 其實,利用JNI也可以做到直接更改動態連結函式庫裡頭的變數,動態連結函式庫裡頭的函式也可以直接更改java程式中的變數,只不過本文章重點並非在JNI功能的介紹,所以並沒有提及. 另外關於CPU特徵的偵測,我們只是簡單地偵測幾個CPU的特性,較複雜的還有偵測CPU的時脈等特徵,在Intel的網站上我們也可以找到名為cpuinfo.zip的樣本. 期望這篇文章可以讓目前正在使用java,又想充分利用處理器特性來做最佳化的朋友提供一個踏板. 發表人 - conundrum 於 2004/02/14 11:57:16 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |