国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

使用JNI進行混合編程:在Java中調用C/C++本地庫

開發 后端
JNI是Java Native Interface的英文縮寫, 中文翻譯為本地調用, 自從Java 1.1開始就成為了Java標準的一部分。

JNI是Java Native Interface的英文縮寫, 中文翻譯為本地調用, 自從Java 1.1開始就成為了Java標準的一部分。

C/C++是系統級的編程語言, 可以用來開發任何和系統相關的程序和類庫, 但是Java本身編寫底層的應用比較難實現, 使用JNI可以調用現有的本地庫, 極大地靈活了Java的開發。

C/C++的效率是目前***的語言, 可以使用C/C++來實現一些實時性非常高的部分. C/C++和Java本身都是非常流行的編程語言, 一些大型軟件中經常使用語言之間的混合編程。

鑒于目前網絡上JNI的文章不是特別多, 我將自己的一些總結寫在這里. 如有錯漏, 歡迎指正!

Java調用C/C++大概有這樣幾個步驟

  • 編寫帶有native方法的Java類, 使用javac工具編譯Java類
  • 使用javah來生成與native方法對應的頭文件
  • 實現相應的頭文件, 并編譯為動態鏈接庫(windows下是.dll, linux下是.so)

下面就完整的介紹一個簡單的Java調用C/C++的例子, 這個例子是來自http://www.ibm.com/developerworks/cn/education/java/j-jni/index.html, 不過其中有一些錯誤, 這個文章是非常不錯的JNI學習資料, 但是非常古老.

編寫Java類

我們來編寫一個Sample1的java類

  1. public class Sample1 {  
  2.     public native int intMethod(int n);  
  3.     public native boolean booleanMethod(boolean bool);  
  4.     public native String stringMethod(String text);  
  5.     public native int intArrayMethod(int[] intArray);  
  6.        
  7.     public static void main(String[] args) {  
  8.         System.loadLibrary("Sample1");  
  9.         Sample1 sample = new Sample1();  
  10.         int square = sample.intMethod(5);  
  11.         boolean bool = sample.booleanMethod(true);  
  12.         String text = sample.stringMethod("Java");  
  13.         int sum = sample.intArrayMethod(new int[]{1,2,3,4,5,8,13});  
  14.            
  15.         System.out.println("intMethod: " + square);  
  16.         System.out.println("booleanMethod: " + bool);  
  17.         System.out.println("stringMethod: " + text);  
  18.         System.out.println("intArrayMethod: " + sum);  
  19.     }  

上面有4個native方法, 分別是4種類型的參數, int, boolean, String, int[].

其中有一句比較重要, 這句話加載了動態類庫

  1. System.loadLibrary("Sample1"); 

在windows下加載的就是Sample1.dll, 在linux下加載的就是Sample1.so。

本文使用的windowws, 所以后面使用Sample1.dll來表示Sample1動態鏈接庫。

注意:不可以在代碼中寫上后綴dll或so. 還要保證Sample1.dll在path路徑中. 這個Sample1.dll是我們后面需要編譯出來的東西。

4個native方法就是我們需要用C來實現的方法。

編譯Sample1.java, 使用命令行(windows是cmd, linux下一般是bash)

>javac Sample1.java

可以看到Sample1.class文件

使用javah生成頭文件

在命令行中運行

>javah Sample1

可以在目錄下看到一個新文件Sample1.h

  1. /* DO NOT EDIT THIS FILE - it is machine generated */ 
  2. #include <jni.h>  
  3. /* Header for class Sample1 */ 
  4.    
  5. #ifndef _Included_Sample1  
  6. #define _Included_Sample1  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /*  
  11.  * Class:     Sample1  
  12.  * Method:    intMethod  
  13.  * Signature: (I)I  
  14.  */ 
  15. JNIEXPORT jint JNICALL Java_Sample1_intMethod  
  16.   (JNIEnv *, jobject, jint);  
  17.    
  18. /*  
  19.  * Class:     Sample1  
  20.  * Method:    booleanMethod  
  21.  * Signature: (Z)Z  
  22.  */ 
  23. JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod  
  24.   (JNIEnv *, jobject, jboolean);  
  25.    
  26. /*  
  27.  * Class:     Sample1  
  28.  * Method:    stringMethod  
  29.  * Signature: (Ljava/lang/String;)Ljava/lang/String;  
  30.  */ 
  31. JNIEXPORT jstring JNICALL Java_Sample1_stringMethod  
  32.   (JNIEnv *, jobject, jstring);  
  33.    
  34. /*  
  35.  * Class:     Sample1  
  36.  * Method:    intArrayMethod  
  37.  * Signature: ([I)I  
  38.  */ 
  39. JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod  
  40.   (JNIEnv *, jobject, jintArray);  
  41.    
  42. #ifdef __cplusplus  
  43. }  
  44. #endif  
  45. #endif 

我們可以看到其中有四個函數聲明, Java_完整類名_方法名, 完整類名包括了包名, 例如demo.Sample1是完整類名, 對應的這里就是demo_Sample1.

在注釋中我們可以看到這樣一個東西 Signature, 這個是方法的簽名. 關于Signature, 下面通過一個表格來說明。

java類型 Signature 備注
boolean Z  
byte B  
char C  
short S  
int I  
long L  
float F  
double D  
void V  
object L用/分割的完整類名 例如: Ljava/lang/String表示String類型
Array [簽名 例如: [I表示int數組, [Ljava/lang/String表示String數組
Method (參數簽名)返回類型簽名 例如: ([I)I表示參數類型為int數組, 返回int類型的方法

上面頭文件的***個函數聲明

  1. JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *, jobject, jint); 

注釋中的簽名是 Signature: (I)I

在每個函數的參數列表中都有JNIEnv *和 jobject兩個參數, 這兩個參數稍候說明。

實現頭文件中的函數

可以使用C語言來實現, 也可以使用C++來實現, 下面先說說C語言的實現。

  1. #include "Sample1.h" 
  2. #include <string.h>  
  3.    
  4. JNIEXPORT jint JNICALL Java_Sample1_intMethod  
  5.   (JNIEnv *env, jobject obj, jint num)  
  6. {  
  7.     return num * num;  
  8. }  
  9.    
  10. JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod  
  11.   (JNIEnv *env, jobject obj, jboolean boolean)  
  12. {  
  13.     return !boolean;  
  14. }  
  15.    
  16. JNIEXPORT jstring JNICALL Java_Sample1_stringMethod  
  17.   (JNIEnv *env, jobject obj, jstring string)  
  18. {  
  19.     const char* str = (*env)->GetStringUTFChars(env, string, 0);  
  20.     char cap[128];  
  21.     strcpy(cap, str);  
  22.     (*env)->ReleaseStringUTFChars(env, string, 0);  
  23.     return (*env)->NewStringUTF(env, strupr(cap));  
  24. }  
  25.    
  26. JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod  
  27.   (JNIEnv *env, jobject obj, jintArray array)  
  28. {  
  29.     int i, sum = 0;  
  30.     jsize len = (*env)->GetArrayLength(env, array);  
  31.     jint *body = (*env)->GetIntArrayElements(env, array, 0);  
  32.        
  33.     for (i = 0; i < len; ++i)  
  34.     {  
  35.         sum += body[i];  
  36.     }  
  37.     (*env)->ReleaseIntArrayElements(env, array, body, 0);  
  38.     return sum;  

(*env)->GetStringUTFChars()這個方法, 是用來在Java和C之間轉換字符串的, 因為Java本身都使用了雙字節的字符, 而C語言本身都是單字節的字符, 所以需要進行轉換.

JNIEnv *是每個函數都有的參數, 它包含了很多有用的方法, 使用起來類似Java的反射, 也提供了這樣一個編碼轉換的函數.

GetStringUTFChars()和NewStringUTF(), ***個是從UTF8轉換為C的編碼格式, 第二個是根據C的字符串返回一個UTF8字符串.

ReleaseStringUTFChars()是用來釋放對象的, 在Java中有虛擬機進行垃圾回收, 但是在C語言中, 這些對象必須手動回收. 否則可能造成內存泄漏.

函數的名字一眼看到就可以猜出功能, jni.h中的大部分函數名都是這樣.

如果是C++的話, 這段代碼該怎么寫?

下面是C++的代碼

  1. #include "Sample1.h"  
  2. #include <string.h>  
  3.    
  4. JNIEXPORT jint JNICALL Java_Sample1_intMethod  
  5.   (JNIEnv *env, jobject obj, jint num)  
  6. {  
  7.     return num * num;  
  8. }  
  9.    
  10. JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod  
  11.   (JNIEnv *env, jobject obj, jboolean boolean)  
  12. {  
  13.     return !boolean;  
  14. }  
  15.    
  16. JNIEXPORT jstring JNICALL Java_Sample1_stringMethod  
  17.   (JNIEnv *env, jobject obj, jstring string)  
  18. {  
  19.     const char* str = env->GetStringUTFChars(string, 0);  
  20.     char cap[128];  
  21.     strcpy(cap, str);  
  22.     env->ReleaseStringUTFChars(string, 0);  
  23.     return env->NewStringUTF(strupr(cap));  
  24. }  
  25.    
  26. JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod  
  27.   (JNIEnv *env, jobject obj, jintArray array)  
  28. {  
  29.     int i, sum = 0;  
  30.     jsize len = env->GetArrayLength(array);  
  31.     jint *body = env->GetIntArrayElements(array, 0);  
  32.        
  33.     for (i = 0; i < len; ++i)  
  34.     {  
  35.         sum += body[i];  
  36.     }  
  37.     env->ReleaseIntArrayElements(array, body, 0);  
  38.     return sum;  

上述兩端代碼非常相似, 只有一個不同點

C代碼: (*env)->GetStringUTFChars(env, string, 0);

C++代碼: env->GetStringUTFChars(string, 0);

C語言中使用的是結構體的函數指針, 而在C++中使用的還是struct, 我們知道struct在C++中和class的功能是幾乎一樣的, struct也可以用來定義類, 所以env在C++中是個類對象的指針.

編譯和運行

這里使用的是微軟編譯器, 編譯C語言版的dll

>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.c -FeSample1.dll

編譯C++版本的dll

>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.cpp -FeSample1.dll

運行

>java Sample1

注意: 64位版本的JDK可能會在運行時報錯:

java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

如果您有這樣的錯誤, 請使用32位的JDK來重新運行.

運行結果如下:

intMethod: 25 
booleanMethod: false 
stringMethod: JAVA 
intArrayMethod: 36

源代碼下載: Sample1.zip

運行其中的build&run.bat文件即可, 如有錯誤請根據實際情況修改其中的一些參數.

DLL工程文件VC6.0和VS2010的: VC6.0&VS2010.zip

參考文獻:

  1. Scott Stricker, 用 JNI 進行 Java 編程, http://www.ibm.com/developerworks/cn/education/java/j-jni/section2.html
  2. JDK 6u30 docs, Java Native Interface Specification, Chapter 3 JNI Types and Data Structures, Type Signatures.

原文鏈接:http://www.cnblogs.com/icejoywoo/archive/2012/02/22/2363709.html

【編輯推薦】

  1. Java通過SSH2協議運行遠程程序
  2. Java Socket編程:初識TCP Socket
  3. Java Socket編程:如何識別網絡主機
  4. Java Socket編程:基本的術語和概念
  5. Java集合類ArrayList循環中刪除特定元素

 

責任編輯:林師授 來源: icejoywoo的博客
相關推薦

2012-04-28 15:28:21

JNI混合編程Java

2009-07-20 09:53:43

Java混合編程

2011-07-01 14:55:28

Qt QML C++

2012-04-16 13:22:56

CORBAJavaC++

2011-02-15 13:12:02

JavaC++

2010-01-20 14:35:55

C++調用

2010-01-18 17:14:50

C++語言

2010-01-12 15:13:37

Visual C++環

2009-06-15 14:48:13

Visual C++本狀態管理

2011-08-22 17:13:00

LuaC++函數

2011-05-18 17:15:45

2023-03-15 15:58:11

Python動態庫C++

2010-01-11 09:28:34

C++編程

2010-01-20 10:49:29

Visual C++界

2010-01-26 13:55:07

C++標準模板庫

2024-01-26 16:32:08

2021-07-26 05:26:54

Androidc++java

2019-08-28 14:21:39

C++C接口代碼

2020-07-31 18:33:56

C++編程語言

2009-06-19 16:55:47

JNI調用C語言
點贊
收藏

51CTO技術棧公眾號

欧美专区18| 麻豆传传媒久久久爱| 亚洲精品国产无天堂网2021| 一区视频网站| 日本午夜激情视频| 中文字幕在线看视频国产欧美在线看完整 | 国产美女久久| 免费看日本毛片| 播播国产欧美激情| 99精品1区2区| 都市激情久久| 欧美福利网站| 亚洲自拍偷拍色片视频| 欧美日本国产视频| 免费观看在线色综合| 亚洲承认视频| 欧美一级特黄a| 国产精品看片资源| 日本乱码高清不卡字幕| 三级影片在线观看欧美日韩一区二区 | 91av一区| 在线观看高清免费视频| 日本三级韩国三级久久| 亚洲第一精品在线| 亚洲美女视频在线免费观看| 怡红院在线播放| 一本色道久久综合亚洲精品婷婷 | 欧美极品美女电影一区| 亚洲天堂av一区| 亚洲大全视频| av电影免费在线看| 欧美三级一级片| 国产第一区电影| 5月丁香婷婷综合| 国产高清成人在线| 国产精品任我爽爆在线播放| 免费一级淫片| 久久综合一区| 伊人av综合网| 亚洲女人****多毛耸耸8| 91久久国产| 三级在线看中文字幕完整版| 麻豆传传媒久久久爱| 国产精品一香蕉国产线看观看| 51午夜精品国产| 99免费精品视频| 成人羞羞网站| 日本理论片午伦夜理片在线观看| 18岁视频在线观看| 91精品一区二区| 亚洲乱码国产乱码精品精天堂| 国产精品欧美久久久久无广告 | 欧美高清性xxxxhd| 在线观看日韩av| 亚洲精品成人在线| 久久久久久久欧美精品| 综合激情五月婷婷| 国产精品四虎| 男人日女人逼逼| 国产美女精品免费电影| 日韩精品在线视频| 亚洲日本护士毛茸茸| 国产情侣一区| 日韩精品成人| 一区二区三区视频在线观看视频| 欧美 国产 综合| yellow视频在线观看一区二区| 亚洲欧美一区二区三区久久| 亚洲日穴在线视频| 欧美aa在线视频| 色婷婷热久久| 九九久久国产| 日日夜夜精品一区| 日本成人免费| 成年人黄色在线观看| 国产精品免费久久久久久| 亚洲欧美国产制服动漫| 亚洲午夜激情网页| 国产一区二区三区av电影| 成人毛片免费看| 日本h片久久| 亚洲免费视频一区二区三区| 国产精品毛片一区二区三区| 99久久.com| 国产欧美日韩一区二区三区在线| 日韩大胆成人| 国产日韩一区二区三区在线播放| 久久久99免费| 日韩精品一区二区三区四区| 97热精品视频官网| 亚洲 国产 欧美一区| 2001个疯子在线观看| 久久久久久自在自线| 亚洲精品xxxx| 国产精品十八以下禁看| 国产午夜视频| 国产一区二区电影在线观看| 性爽视频在线| 欧美wwwww| 99精品欧美一区| 伊人av综合网| 国产午夜精品视频免费不卡69堂| 日本亚洲欧洲精品| 国产精品v日韩精品v在线观看| 四虎亚洲精品| 麻豆成人免费电影| 日韩国产精品视频| 精品在线一区| 淫片在线观看| 国产一区导航| 国内精品久久久| 黄a大片av永久免费| 亚洲天堂免费| 国产精品久久久久一区 | 亚洲激情一二三区| 国产专区一区二区| 久久婷婷综合色| 天天色天天射天天综合网| 动漫av一区| 视频一区中文字幕国产| 91视频com| 亚洲乱码一区二区三区在线观看| 欧美一区在线视频| 国产精品91在线| 亚洲电影网站| 在线免费黄色| 午夜精品毛片| 亚洲女同ⅹxx女同tv| 欧美三级日韩三级| 国产一区精品在线| 成人嫩草影院免费观看| 超级碰碰久久| 国产99亚洲| 全国精品久久少妇| 午夜精品视频一区| 久久久久久国产精品久久| 男女裸体影院高潮| 碰碰在线视频| 秋霞午夜av一区二区三区| 欧美日韩人人澡狠狠躁视频| 国产精品久久久久久搜索| 久久人体av| 欧美三级一区二区| 无码人妻精品一区二区三区在线| 国语精品一区| 精品亚洲一区二区三区在线播放| 日韩欧美亚洲在线| 中文字幕在线观| 成人小视频免费观看| 99re6在线| 日本暖暖在线视频| 麻豆91精品91久久久的内涵| 欧美乱妇40p| 日日夜夜综合| 伊人男人综合视频网| 激情校园亚洲图片| 麻豆中文一区二区| 国产精品99久久久久久白浆小说 | 成人福利视频在线观看| 在线观看三级视频| 福利一区福利二区微拍刺激| 久久亚洲中文字幕无码| 日韩精品永久网址| 欧美亚洲日本国产| 日韩一区国产在线观看| 色综合桃花网| 国产精品二区一区二区aⅴ污介绍| 欧美精品激情在线| 国产一二在线观看| 亚洲成人免费看| 先锋在线亚洲| 一区二区三区成人在线视频| 青青在线视频免费| 91tv官网精品成人亚洲| 91精品成人久久| 日韩精品一区二区三区中文| 一区二区国产盗摄色噜噜| 国产在线视频综合| 先锋影音国产一区| 亚洲无线码在线一区观看| 五月天中文字幕一区二区| 亚洲国产精品影院| 欧美在线影院一区二区| 欧美高清性hdvideosex| 亚洲国内精品在线| 色偷偷888欧美精品久久久| 欧美伊久线香蕉线新在线| 91精品国产综合久久久久久久久| 成人综合av网| 日本不卡二区| 黄色一级在线视频| 九草视频在线观看| 狠狠狠综合7777久夜色撩人| 日本美女在线中文版| 国产污视频在线播放| 视频在线日韩| 狠狠操综合网| 亚洲精品激情| 成人午夜电影网站| 亚洲综合一二区|