Linux下JNI的demo


java访问C/C++有6步
1.写java文件
2.编译java生成class
3.生成C/C++头文件。
4.写C/C++文件
5.编译生成dll(Window下)或so文件
6.运行java程序
下面介绍ubutun下一个JNI例子

1.编写Sample1.java文件:

 
  1. public class Sample1  
  2.  {  
  3. public native int intMethod(int n);  
  4. public native boolean booleanMethod(boolean bool);  
  5. public native String stringMethod(String text);  
  6. public native int intArrayMethod(int[] intArray);  
  7.   
  8. public static void main(String[] args)  
  9. {  
  10. System.loadLibrary("Sample1");  
  11. Sample1 sample = new Sample1();  
  12. int square = sample.intMethod(5);  
  13. boolean bool = sample.booleanMethod(true);  
  14. String text = sample.stringMethod("JAVA");  
  15. int sum = sample.intArrayMethod(  
  16. new int[]{1,1,2,3,5,8,13} );  
  17.   
  18. System.out.println("intMethod: " + square);  
  19. System.out.println("booleanMethod: " + bool);  
  20. System.out.println("stringMethod: " + text);  
  21. System.out.println("intArrayMethod: " + sum);  
  22. }  
  23. }  
 两个地方要注意,
 一。上面的方法都用到了native关键字。
 二。System.loadLibrary("Sample1");这句中"Sample1"是我们在第5步中得到的库的名字,在window下是"Sample1.dll",在unix下要加前缀"lib",即"libSample1.so"。
 
2.编译java文件:
javac  Sample1.java
    无错生成Sample1.class文件
3.生成C/C++头文件
javah  Sample1
    生成Sample1.h
使用命令 cat  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. JNIEXPORT jint JNICALL Java_Sample1_intMethod  
  12. (JNIEnv *, jobject, jint);  
  13.   
  14. JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod  
  15. (JNIEnv *, jobject, jboolean);  
  16.   
  17. JNIEXPORT jstring JNICALL Java_Sample1_stringMethod  
  18. (JNIEnv *, jobject, jstring);  
  19.   
  20. JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod  
  21. (JNIEnv *, jobject, jintArray);  
  22.   
  23. #ifdef __cplusplus   
  24. }  
  25. #endif   
  26. #endif  
我们可以对比看看java文件中对应的方法
 4.编写C/C++代码

   Sample1.c:

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

Sample1.cpp:

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

两个差别就是JNIEnv这个类
  C中使用 jsize len = (*env)->GetArrayLength(env,array);
  C++中使用 jsize len = env->GetArrayLength(env,array);  
 
5.生成共享库文件
 编译Sample1.c文件
 gcc -fPIC -D_REENTRANT -I/usr/lib/java/include -I/usr/lib/java/include/linux -c Sample1.c 
 编译用到了jdk include中jni.h,include/linux中jni_md.h两个头文件
 /usr/lib/java/include        是jin.h路径
 /usr/lib/java/include、linux 是jni_md.h路径
 此时生成Sampel.o文件
 运行:
 gcc -shared Sample1.o -o libSample1.so
 生成libSample1.so


6.运行java程序
libSample1.so文件拷贝到java的加载库LD_LIBRARY_PATH指向的路径中:
如果没有足够权限,可以这样:
(1).在/home下建立一个用来存放.so库文件的目录,比如/home/xxx/lib
(2).把libSample1.so文件拷贝到该目录下
(3).运行:export LD_LIBRARY_PATH=/home/xxx/lib  (只在当前shall下有效...)
现在运行java Sample1
一切正常后,可以看到运行結果输出:
intMethod: 25
booleanMethod: false
stringMethod: JAVA
intArrayMethod: 33
完成第一个JNI程序。

相关内容