JNI與JNA性能比較
在介紹JNA時,提到了JNA是基於JNI的,是在JNI上封裝了一層,JNI性能不如JNA。最近在網上看到篇簡單的比較這兩者性能的文檔,感覺不錯,現轉載一下:
分別用JNI和JNA的方式建立dll,dll中包含一個get方法和一個set方法,在Java端進行循環調用1000*1000次,比較所耗費的時間。
JNI和JNA調用的不是同一個dll,但是功能和代碼基本相同。本測試從一定角度反映他們的性能。
【JNI實現】
先編寫Java相關的native方法:
- package crayon.jni;
- public class JNITest {
- public native static void set(int i);
- public native static int get();
- static{
- System.loadLibrary("JNITest");
- }
- }
然后利用javah命令從上述帶native方法的class文件導出.h頭文件,並編寫C代碼實現為:
- #include "stdafx.h"
- #include "JNITest.h"
- long tmp = 0;
- JNIEXPORT void JNICALL Java_crayon_jni_JNITest_set
- (JNIEnv *, jclass, jint value){
- tmp = value;
- }
- JNIEXPORT jint JNICALL Java_crayon_jni_JNITest_get
- (JNIEnv *, jclass){
- return tmp;
- }
生成dll動態鏈接庫,並測試,最后時間為:
- package crayon.jni;
- public class TestJNI {
- public static void main(String[] args) {
- long beginTime = System.currentTimeMillis();
- int i;int j;
- for(i=0;i<1000;i++){
- for(j=0;j<1000;j++){
- JNITest.set(i*j);
- JNITest.get();
- }
- }
- long totalTime = System.currentTimeMillis()-beginTime;
- System.out.println("JNI消耗的總時間(ms):"+totalTime);
- }
- }
- JNI消耗的總時間(ms):16
【JNA實現】
對於JNA,我們可以直接先寫C代碼了,如下分別為.h文件和.cpp文件:
- #ifdef JNATEST_EXPORTS
- #define JNATEST_API __declspec(dllexport)
- #else
- #define JNATEST_API __declspec(dllimport)
- #endif
- extern "C" {
- JNATEST_API void set(long l);
- JNATEST_API long get();
- }
- #include "stdafx.h"
- #include "JNATest.h"
- long tmp;
- JNATEST_API void set(long l){
- tmp = l;
- }
- JNATEST_API long get(){
- return tmp;
- }
直接寫Java端代碼調用上述導出的dll文件,注意別忘記引入JNA相關的jar包,代碼為:
- package crayon.jna;
- import com.sun.jna.Library;
- import com.sun.jna.Native;
- public interface JNATest extends Library {
- JNATest INSTANCE = (JNATest) Native.loadLibrary(
- "D:/CC/Tools_Tool_ITT_StdPrj_Dev/PF_Tools_VOB/Tools_SubTool/src/JNATest/Release/JNATest", JNATest.class);
- public void set(int i);
- public int get();
- }
測試代碼和結果為:
- package crayon.jna;
- import com.sun.jna.Library;
- import com.sun.jna.Native;
- public interface JNATest extends Library {
- JNATest INSTANCE = (JNATest) Native.loadLibrary(
- "D:/CC/Tools_Tool_ITT_StdPrj_Dev/PF_Tools_VOB/Tools_SubTool/src/JNATest/Release/JNATest", JNATest.class);
- public void set(int i);
- public int get();
- }
- JNA消耗的總時間(ms):2593
綜上比較:JNI 16ms << JNA 2593ms!!!性能差距還蠻大的!!
本着赤果果地實事求是地態度,我在自己的lenovo 昭陽K46(XP,處理器i3,內存升級4G--實際使用3G)的機器上測試了一下,結果為(取10次平均):JNI 120.5ms JNA 4535.8ms !!我的本本貌似不是很給力,但測試結果整體趨勢差不多!
這次試驗,本身也有一個收獲,就是:在JNI(或JNA)應用中,在Java端,我們會有一個對象,其中調用的方法都會映射到本地代碼中,只要我們是同一個Java對象,我們同樣可以將一個值在一次本地方法調用中設置到對象里,然后在下一次調用中使用。當然這個值是保存在本地代碼中的。
