因爲JNI調用C和調用C++差很少,並且C++中能夠混合寫C代碼,因此這裏主要是寫關於JNI調用C++的部分。html
源代碼連接:http://files.cnblogs.com/GDUT/jni-demo.rarjava
1. 普通Java類(包含測試方法):MyJNI.java數組
1 public class MyJNI { 2 3 //加載動態連接庫 4 static { 5 System.out.println("開始加載動態連接庫"); 6 System.loadLibrary("MyJNI"); 7 System.out.println("動態連接庫加載完畢。"); 8 } 9 10 public native void go(); 11 12 public native void run(); 13 14 public native String getName(); 15 16 public native int[] sort(int[] array); 17 18 //測試 19 public static void main(String[] args) { 20 MyJNI jni = new MyJNI(); 21 int[] array = {5, 3, 6, 35, 74, 8}, sortedArray; 22 23 jni.run(); 24 jni.go(); 25 jni.getName(); 26 sortedArray = jni.sort(array); 27 //因爲這是本地方法調用,這裏的數組和日常的數組的引用不太同樣。 28 29 for(int i=0; i<sortedArray.length; i++){ 30 System.out.print(sortedArray[i] + "\t"); 31 } 32 33 } 34 }
2. 由Java類編譯後生成的C++頭文件:MyJNI.h函數
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class MyJNI */ 4 5 #ifndef _Included_MyJNI 6 #define _Included_MyJNI 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: MyJNI 12 * Method: go 13 * Signature: ()V 14 */ 15 JNIEXPORT void JNICALL Java_MyJNI_go 16 (JNIEnv *, jobject); 17 18 /* 19 * Class: MyJNI 20 * Method: run 21 * Signature: ()V 22 */ 23 JNIEXPORT void JNICALL Java_MyJNI_run 24 (JNIEnv *, jobject); 25 26 /* 27 * Class: MyJNI 28 * Method: getName 29 * Signature: ()Ljava/lang/String; 30 */ 31 JNIEXPORT jstring JNICALL Java_MyJNI_getName 32 (JNIEnv *, jobject); 33 34 /* 35 * Class: MyJNI 36 * Method: sort 37 * Signature: ([I)[I 38 */ 39 JNIEXPORT jintArray JNICALL Java_MyJNI_sort 40 (JNIEnv *, jobject, jintArray); 41 42 #ifdef __cplusplus 43 } 44 #endif 45 #endif
3. 須要調用的C++函數的相關文件:MyJNIImpl.cpp測試
1 #include <jni.h> 2 #include "MyJNI.h" 3 #include <stdio.h> 4 5 6 /* 7 * Class: MyJNI 8 * Method: go 9 * Signature: ()V 10 */ 11 JNIEXPORT void JNICALL Java_MyJNI_go 12 (JNIEnv * env, jobject jobj){ 13 14 printf("I am going....\n"); 15 } 16 17 /* 18 * Class: MyJNI 19 * Method: run 20 * Signature: ()V 21 */ 22 JNIEXPORT void JNICALL Java_MyJNI_run 23 (JNIEnv * env, jobject jobj){ 24 25 printf("I am running....\n"); 26 } 27 28 /* 29 * Class: MyJNI 30 * Method: getName 31 * Signature: ()Ljava/lang/String; 32 */ 33 JNIEXPORT jstring JNICALL Java_MyJNI_getName 34 (JNIEnv * env, jobject job){ 35 36 printf("I am GDUTtiantian, go with me.\n"); 37 //將字符串轉化爲jstring類型 38 //jstring就是對應java的String類型 39 jstring p = env->NewStringUTF("GDUTtiantian"); 40 return p; 41 } 42 43 /* 44 * Class: MyJNI 45 * Method: sort 46 * Signature: ([I)[I 47 */ 48 JNIEXPORT jintArray JNICALL Java_MyJNI_sort 49 (JNIEnv * env, jobject jobj, jintArray array){ 50 51 jint* arr;//定義一個整形指針 52 int sum=0; 53 //對於整形數組的處理,主要有GetIntArrayElements與GetIntArrayRegion 54 //第一種方法 55 arr = env->GetIntArrayElements(array, NULL);//獲得一個指向原始數據類型內容的指針 56 jint length = env->GetArrayLength(array);//獲得數組的長度 57 58 for(int i=0; i<length; i++){ 59 for(int j=i+1; j<length; j++){ 60 if(arr[i] > arr[j]){ 61 jint temp = arr[i]; 62 arr[i] = arr[j]; 63 arr[j] = temp; 64 } 65 } 66 } 67 68 69 for(int i=0; i<length; i++){ 70 printf("%d ", arr[i]); 71 } 72 73 printf("\n排序完成\n"); 74 75 jintArray javaArray = env->NewIntArray(length); 76 env->SetIntArrayRegion(javaArray, 0, length, arr); 77 78 return javaArray;//返回排序後的數組 79 }
編譯以後,生成一個動態連接庫文件:MyJNI.dllspa
在Java類中就是經過加載這個庫文件,調用其中的相關函數。.net
調用的相關命令:3d
1 C:\Users\Administrator\Desktop>java HelloJNI 2 Exception in thread "main" java.lang.UnsupportedClassVersionError: HelloJNI : Unsupported major.minor version 51.0 3 at java.lang.ClassLoader.defineClass1(Native Method) 4 at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) 5 at java.lang.ClassLoader.defineClass(ClassLoader.java:615) 6 at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) 7 at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) 8 at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 9 at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 10 at java.security.AccessController.doPrivileged(Native Method) 11 at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 12 at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 13 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 14 at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 15 Could not find the main class: HelloJNI. Program will exit.
這個是JAVA虛擬機的版本低於編譯器的問題,若是你用一個編譯編譯以後,而後把.class文件移動到另外一個環境下執行,可能會出現這個問題。指針
2. 第二個異常code
1 C:\Users\Administrator\Desktop>javac *.java 2 3 C:\Users\Administrator\Desktop>java HelloJNI 4 Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Administrator\Desktop\hello.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform 5 at java.lang.ClassLoader$NativeLibrary.load(Native Method) 6 at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1807) 7 at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732) 8 at java.lang.Runtime.loadLibrary0(Runtime.java:823) 9 at java.lang.System.loadLibrary(System.java:1028) 10 at HelloJNI.<clinit>(HelloJNI.java:3) 11 Could not find the main class: HelloJNI. Program will exit.
動態連接庫.dll是32位,而JVM是64位,不匹配;能夠安裝一個32位的JVM;或者在64位環境下從新編譯一個新的.dll文件。
3. 第三個異常
1 C:\Users\Administrator\Desktop\jni>g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp 2 In file included from MyJNIImpl.cpp:1: 3 MyJNI.h:2:17: jni.h: No such file or directory 4 In file included from MyJNIImpl.cpp:1: 5 MyJNI.h:15: error: expected constructor, destructor, or type conversion before "void" 6 MyJNI.h:15: error: expected `,' or `;' before "void" 7 MyJNI.h:23: error: expected constructor, destructor, or type conversion before "void" 8 MyJNI.h:23: error: expected `,' or `;' before "void" 9 MyJNI.h:31: error: `JNIEXPORT' does not name a type 10 MyJNI.h:39: error: `JNIEXPORT' does not name a type 11 MyJNIImpl.cpp:10: error: expected constructor, destructor, or type conversion before "void" 12 MyJNIImpl.cpp:10: error: expected `,' or `;' before "void" 13 MyJNIImpl.cpp:21: error: expected constructor, destructor, or type conversion before "void" 14 MyJNIImpl.cpp:21: error: expected `,' or `;' before "void" 15 MyJNIImpl.cpp:32: error: `JNIEXPORT' does not name a type 16 MyJNIImpl.cpp:47: error: `JNIEXPORT' does not name a type
這個報錯主要是找不到jni.h文件,通常的緣由:JAVA_HOME的路徑有問題,注意這個路徑是安裝路徑。用命令設置下,若是設置仍是報這個錯誤,那麼就到環境變量那裏修改。
參考資料:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
JNI類型轉換:http://www.cnblogs.com/lgydqy/archive/2012/02/28/2371592.html
函數
Java 數組類型
本地類型
GetBooleanArrayElements
jbooleanArray
jboolean
GetByteArrayElements
jbyteArray
jbyte
GetCharArrayElements
jcharArray
jchar
GetShortArrayElements
jshortArray
jshort
GetIntArrayElements
jintArray
jint
GetLongArrayElements
jlongArray
jlong
GetFloatArrayElements
jfloatArray
jfloat
GetDoubleArrayElements
jdoubleArray
jdouble
歡迎討論交流, 個人主頁:http://www.cnblogs.com/GDUT/
個人郵箱:zone.technology.exchange@gmail.com