1,首先,在android根目錄建立test 目錄,在test目錄下再建立test目錄,進入
2,進入test目錄後vim HelloWorld.java
點擊(此處)摺疊或打開
- HelloWorld.java:
- package test;
- public class HelloWorld
- {
- public static void main(String[] args)
- {
- System.loadLibrary("HelloWorld");
- printHello();
- }
- public static native final void printHello();
- }
3,退出test目錄,鍵入命令:../jdk1.5.0_22/bin/javac test/HelloWorld.java,test目錄下將生成HelloWorld.class
4,鍵入../jdk1.5.0_22/bin/javah -o test/Hello.h test.HelloWorld,test目錄下將生成Hello.h
5,在test目錄下創建HelloWorld.cpp文件
點擊(此處)摺疊或打開
- HelloWorld.cpp:
- #include "Hello.h"
- #include <cstdio>
- Void Java_test_HelloWorld_printHello(JNIEnv *, jclass)
- {
- printf("helloworld");
- }
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_OnLoad是java jni技術的一個實現,每次java層加載System.loadLibrary之後,自動會查找改庫一個叫JNI_OnLoad的函數,動態註冊的時候,cpp可以通過實現JNI_OnLoad而完成jni的動態註冊。
1,建立dynamic文件夾,進入,把靜態連接的HelloWorld.java拷貝進來,並且修改package test;爲package dynamic;
2,建立HelloWorld.cpp
點擊(此處)摺疊或打開
- #include "jni.h"
- #include <cstdio>
- // java轉到native層的對應函數
- static int android_print(JNIEnv * env, jclass clazz)
- {
- printf("helloworld");
- }
- // 結構體,分別是java層的函數名稱,簽名,對應的函數指針
- static JNINativeMethod gMethods[] =
- {
- {"printHello", "()V", (void*)android_print},
- };
- // JNI_OnLoad函數實現
- jint JNI_OnLoad(JavaVM* vm, void* reserved)
- {
-
- JNIEnv* env = NULL;
- jint result = -1;
-
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- return -1;
- }
- //如果要註冊,只需要2不,首先FindClass,然後RegisterNatives就可以了
- char className[20] = {"dynamic/HelloWorld"};
- jclass clazz = (env)->FindClass( (const char*)className);
- if((env)->RegisterNatives(clazz, gMethods, 1)< 0)
- {
- return -1;
- }
- //一定要返回版本號,否則會出錯。
- result = JNI_VERSION_1_4;
-
- return result;
- }
然後編譯一下:
編譯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