如何成功調用JNI的實例


1,首先,在android根目錄建立test 目錄,test目錄下再建立test目錄,進入

2,進入test目錄後vim HelloWorld.java


點擊(此處)摺疊或打開

  1. HelloWorld.java:

  2. package test;

  3. public class HelloWorld

  4. {

  5. public static void main(String[] args)

  6. {

  7. System.loadLibrary("HelloWorld");

  8. printHello();

  9. }

  10. public static native final void printHello();

  11. }

3,退出test目錄,鍵入命令:../jdk1.5.0_22/bin/javac test/HelloWorld.javatest目錄下將生成HelloWorld.class

4,鍵入../jdk1.5.0_22/bin/javah -o test/Hello.h test.HelloWorldtest目錄下將生成Hello.h

5,在test目錄下創建HelloWorld.cpp文件


點擊(此處)摺疊或打開

  1. HelloWorld.cpp:

  2. #include "Hello.h"

  3. #include <cstdio>

  4. Void Java_test_HelloWorld_printHello(JNIEnv *, jclass)

  5. {

  6.     printf("helloworld");

  7. }

6,退出test目錄,鍵入 g++ test/HelloWorld.cpp -I ../jdk1.5.0_22/include/ -I ../jdk1.5.0_22/include/linux/ -fPIC -shared -o test/libHelloWorld.so test目錄下將會生成libHelloWorld.so

7,運行../jdk1.5.0_22/bin/java test.HelloWorld 屏幕上會打印出helloworld.

 

出錯情況:

1,如果g++ test/HelloWorld.cpp -I ../jdk1.5.0_22/include/ -fPIC -shared -o test/libHelloWorld.so 雖然jni.h../jdk1.5.0_22/include/,但是如果不加上這邊的目錄-I ../jdk1.5.0_22/include/linux/的話,還是會報一大堆錯誤的。

2,如果運行的時候../jdk1.5.0_22/bin/java test.HelloWorld

java.lang.UnsatisfiedLinkError: no HelloWorld in library path

         at java.lang.Runtime.loadLibrary(Runtime.java)

         at java.lang.System.loadLibrary(System.java)

         at HelloWorld.main(HelloWorld.java)

類似的錯誤,那麼就是因爲LD_LIBRARY_PATH沒有設置正確,用

LD_LIBRARY_PATH=test

 export LD_LIBRARY_PATH

在運行一下就可以了。

參考自:

http://java.sun.com/docs/books/jni/html/start.html

 動態方式:

關於動態方式,java上層的調用和靜態方式是相同的,關鍵是native層的調用有所不同,主要關鍵在於三個地方:

1,  定義調用的JNINativeMethod

2,  定義調用掛鉤的函數

3,  實現JNI_OnLoad函數

JNI_OnLoadjava jni技術的一個實現,每次java層加載System.loadLibrary之後,自動會查找改庫一個叫JNI_OnLoad的函數,動態註冊的時候,cpp可以通過實現JNI_OnLoad而完成jni的動態註冊。

 

1,建立dynamic文件夾,進入,把靜態連接的HelloWorld.java拷貝進來,並且修改package test;package dynamic;

2,建立HelloWorld.cpp

 


點擊(此處)摺疊或打開

  1. #include "jni.h"

  2. #include <cstdio>

  3. // java轉到native層的對應函數

  4. static int android_print(JNIEnv * env, jclass clazz)

  5. {

  6.     printf("helloworld");

  7. }


  8. // 結構體,分別是java層的函數名稱,簽名,對應的函數指針

  9. static JNINativeMethod gMethods[] =

  10. {

  11.     {"printHello", "()V", (void*)android_print},

  12. };

  13. // JNI_OnLoad函數實現

  14. jint JNI_OnLoad(JavaVM* vm, void* reserved)

  15. {

  16.    

  17.     JNIEnv* env = NULL;

  18.     jint result = -1;

  19.  

  20.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

  21.         return -1;

  22. }

  23. //如果要註冊,只需要2不,首先FindClass,然後RegisterNatives就可以了

  24.     char className[20] = {"dynamic/HelloWorld"};

  25.     jclass clazz = (env)->FindClass( (const char*)className);

  26.     if((env)->RegisterNatives(clazz, gMethods, 1)< 0)

  27.     {

  28.         return -1;

  29. }

  30. //一定要返回版本號,否則會出錯。

  31.     result = JNI_VERSION_1_4;

  32.    

  33.         return result;

  34. }

然後編譯一下:

編譯java

../jdk1.5.0_22/bin/javac dynamic/HelloWorld.java

編譯cpp生成.so

g++ dynamic/HelloWorld.cpp -I ../jdk1.5.0_22/include/ -I ../jdk1.5.0_22/include/linux/ -fPIC -shared -o dynamic /libHelloWorld.so dynamic目錄下將會生成libHelloWorld.so

設置LD_LIBRARY_PATH環境變臉

運行Java

../jdk1.5.0_22/bin/java dynamic.HelloWorld 屏幕上會打印出helloworld

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章