java工作筆記:web 程式設計中關於jni和jna兩種工具操作和效能對比測試
阿新 • • 發佈:2019-01-06
第一次發部落格有點緊張哈。
最近剛剛公司轉崗從底層C語言的編寫到做Java的web restful架構。其中需要呼叫底層C++程式碼庫。所以對於選擇哪種方法從Java呼叫C的程式碼做了簡單地學習和對比測試。在這裡把他們貼出了。希望能有大神出來指點指點哈。
這裡我百度了下JAVA調C的方式主要有兩種:JNA和JNI
接下來就是對這兩種方法的操作簡單地學習了一下並放在一起做了個簡單的效能測試(關於兩種方法的具體操作這裡就不詳細敘述了哈)。
使用環境:
Window7作業系統
java編譯器:IntelliJ IDEA 15.0.3
C++編譯器:Visual Studio 2010
powershell
首先是Java的jni程式碼:
public class jniTest {
public static native void test_jni();
static{
System.loadLibrary("helloworld");
}
}
jna的JAVA程式碼:
public interface jnaTest extends Library { jnaTest test_jan = (jnaTest) Native.loadLibrary("helloworld", jnaTest.class); public void print(); }
使用javac和Javah生成.h檔案:
C++程式碼:/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class jniTest */ #ifndef _Included_jniTest #define _Included_jniTest #ifdef __cplusplus extern "C" { #endif /* * Class: jniTest * Method: test_jni * Signature: ()V */ JNIEXPORT void JNICALL Java_jniTest_test_1jni (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
/* jna呼叫 */
__declspec(dllexport) void print()
{
return;
}
/* jni呼叫(相當於把jna呼叫的函式封裝一層) */
void JNICALL Java_jniTest_test_1jni
(JNIEnv *, jclass)
{
print();
}
最後就是JAVA的測試程式碼:
public class app {
public static void main(String[] args){
long startTime = System.currentTimeMillis();
for(int i=0;i<5000;i++){
jnaTest.test_jan.print();
}
long endTime = System.currentTimeMillis();
System.out.println("jna:" + (endTime - startTime)+ " ms");
long startTime1 = System.currentTimeMillis();
for(int i=0;i<5000;i++){
new jniTest().test_jni();
}
long endTime1 = System.currentTimeMillis();
System.out.println("jni:" + (endTime1 - startTime1)+ " ms");
}
}
兩種方法調C分別呼叫5000次計算時間多次測試結果如下:
jna:342 ms
jni:19 ms
jna:280 ms
jni:14 ms
jna:305 ms
jni:12 ms
jna:736 ms
jni:12 ms
jna:347 ms
jni:14 ms
結論:jni的效能比jna快20倍左右。但是jni的操作繁瑣,需要另外生成標頭檔案支援,C程式碼方面依賴jni.h和jni_md.h標頭檔案,而jna只需要在JAVA程式碼中新增一個jna依賴包。在專案開發中具體使用哪種方法還要看專案的具體內容而定。
在我做的專案中,每次一個URL只調用1到5次C庫中的函式,整體影響不大。因此選用比較方便的JNA方法。