转载于:https://www.cnblogs.com/GDUT/p/3806771.html
由于JNI调用C和调用C++差不多,而且C++中可以混合写C代码,所以这里主要是写关于JNI调用C++的部分。
源代码链接:http://files.cnblogs.com/GDUT/jni-demo.rar
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
2. 由Java类编译后生成的C++头文件:MyJNI.h
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include3 /* 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 #include2 #include "MyJNI.h" 3 #include 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 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 NewIntArray(length); 76 env->SetIntArrayRegion(javaArray, 0, length, arr); 77 78 return javaArray;//返回排序后的数组 79 }
编译之后,生成一个动态链接库文件:MyJNI.dll
在Java类中就是通过加载这个库文件,调用其中的相关函数。
调用的相关命令:
- javac *.java
- javah MyJNI
- set JAVA_HOME=D:\SoftwareDeveloping\jdk32bit_1.6
- g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp
- java MyJNI
在操作过程中可能会出现的异常:
- 第一个异常
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. 第二个异常
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.(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