📄 利用java配合bcb 4.0制作cpu特征侦测器.txt
字号:
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.<clinit>(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,又想充分利用处理器特性来做最佳化的朋友提供一个踏板.
本栏文章均来自于互联网,版权归原作者和各发布网站所有,本站收集这些文章仅供学习参考之用。任何人都不能将这些文章用于商业或者其他目的。( ProgramFan.Com )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -