android JNI 系列 一
本文介绍一下用ndk实现jni的方式。
静态注册函数
1. 下载linux版的ndk,windows配环境好像有点麻烦,所以就不说了
2. 配置NDK环境变量:
a.sudo gedit ~/.bashrc
b.在文件中输入如下的内容:
NDKROOT=/home/username/android/ndk/android-ndk-r8
export NDKROOT;
c.更新一下环境配置:source ~/.bashrc
4.创建一个android项目,例子如下:
package org.eshock.jnitest; import android.app.Activity; import android.os.Bundle; public class JNITest extends Activity { public native int plus(int x, int y); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int x = plus(1,2); android.util.Log.d("jni", String.valueOf(x)); } static { System.loadLibrary("jnitest"); } }
5. 编译该android工程,目的是为了在bin下面生成class文件
6. 在项目根目录输入: javah -classpath<bin下面类包的根目录> -d jni org.eshock.jnitest.JNITest, 此时会在项目根目的jni文件夹下生成一个org_eshock_jnitest_JNITest.h 文件,
内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class org_eshock_jnitest_JNITest */ #ifndef _Included_org_eshock_jnitest_JNITest #define _Included_org_eshock_jnitest_JNITest #ifdef __cplusplus extern "C" { #endif /* * Class: org_eshock_jnitest_JNITest * Method: plus * Signature: (II)I */ JNIEXPORT jint JNICALL Java_org_eshock_jnitest_JNITest_plus (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
7.在jni目录手机创建相应的cpp文件,代码如下:
#include "org_eshock_jnitest_JNITest.h" JNIEXPORT jint JNICALL Java_org_eshock_jnitest_JNITest_plus (JNIEnv *env, jobject c, jint a, jint b) { return (a + b); }
8. 在jni文件夹下编写Android.mk文件,内容如下:
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jnitest LOCAL_SRC_FILES :=org_eshock_jnitest_JNITest.c include $(BUILD_SHARED_LIBRARY)
9. 把整个项目文件夹拷到ndk/samples/下面。
10. 进入到ndk/samples/<projectname>/ 下,然后输入 $NDKROOT/ndk-build <module name>
11. 它会在ndk/samples/<projectname>/下生成obj/local/armeabi/lib***.so
动态注册函数
加Java定义如下:
class Test{private native int add(int a, int b);}
1. JNI在加载时,会调用JNI_OnLoad,而卸载时会调用JNI_UnLoad,所以我们可以在JNI_OnLoad里面注册我们的native函数
jint JNI_OnLoad(JavaVM* vm, void* reserved){JNIEnv* env = NULL;jint result = -1;if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){LOGE("ERROR:GetEnv failed\n");goto bail;}assert(env != NULL);if (register_native_function(env) < 0) {LOGE("ERROR: Boa Server native registration failed");goto bail;}result = JNI_VERSION_1_4;bail:return result;}
2. 自已定义register_native_function函数
int register_ckt_BehaviorManager(JNIEnv *env){return jniRegisterNativeMethods(env, "com/lht/Test",gMethods, NELEM(gMethods));}
jniRegisterNativeMethods是JNI注册函数,"com/lht/Test"是对应的Java类,gMethods是一个Java和Native方法对应的数据结构。
typedef struct { const char* name; //Java中申明的Native函数名称 const char* signature; //函数描述,这个具体的写法在以后的篇章里会定义 void* fnPtr; //Natvie函数指针} JNINativeMethod;
3. 定义JNINativeMethod
static JNINativeMethod gMethods[] = {{"add", "(II)I", (void*)com_lht_Test_add},};
4. 实现add函数:
jint com_lht_Test_add(JNIEnv *env, jobject clazz, jint a, jint b){ return (a + b); }
5.Makefile定义
以下方式是用NDK编译的方式
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# 添加代码文件LOCAL_SRC_FILES:= \ com_lht_Test.cpp# 添加头文件LOCAL_C_INCLUDES += \$(JNI_H_INCLUDE) \# 添加相关库文件LOCAL_SHARED_LIBRARIES := \libur \libcutils \# 生成的目标so名称LOCAL_MODULE := libTest_jniLOCAL_MODULE_TAGS := optionalinclude $(BUILD_SHARED_LIBRARY)
NDK_stack
追踪出问题代码的行数
源码:
#include "com_example_testjni_MainActivity.h"JNIEXPORT jint JNICALL Java_com_example_testjni_MainActivity_add(JNIEnv *env, jobject c, jint a, jint b){ char *str = "abc\n"; str[4] = 8; return (a + b);}
F/libc (14337): Fatal signal 11 (SIGSEGV) at 0x752cb0fc (code=2), thread 14337 (example.testjni)I/DEBUG ( 263): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***I/DEBUG ( 263): Build fingerprint: 'eng/debug,test-keys'I/DEBUG ( 263): Revision: '115'I/DEBUG ( 263): pid: 14337, tid: 14337, name: example.testjni >>> com.example.testjni <<<I/DEBUG ( 263): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 752cb0fcI/DEBUG ( 263): r0 00000008 r1 752cb0f8 r2 00000003 r3 00000005I/DEBUG ( 263): r4 6d8b9438 r5 415e68f8 r6 00000004 r7 41535ca0I/DEBUG ( 263): r8 be9b42b8 r9 41535c98 sl 415e6908 fp be9b42ccI/DEBUG ( 263): ip 752c9bb9 sp be9b42b8 lr 41607450 pc 752c9bbe cpsr 000b0030I/DEBUG ( 263): d0 6d6178652f6d6f63 d1 747365742f656c70I/DEBUG ( 263): d2 6e69614d2f696e6a d3 7974697669746341I/DEBUG ( 263): d4 0000000000000000 d5 0000000000000000I/DEBUG ( 263): d6 0000000000000000 d7 4140000000000000I/DEBUG ( 263): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 263): d10 0000000000000000 d11 0000000000000000I/DEBUG ( 263): d12 0000000000000000 d13 0000000000000000I/DEBUG ( 263): d14 0000000000000000 d15 0000000000000000I/DEBUG ( 263): d16 41ad6c7041abbf68 d17 41ac50d041ad1770I/DEBUG ( 263): d18 000000010000012e d19 000000010000016dI/DEBUG ( 263): d20 00000001000012dc d21 00000001000014ebI/DEBUG ( 263): d22 00000001000014fa d23 00000001000014fcI/DEBUG ( 263): d24 0000000000000000 d25 0000000000000000I/DEBUG ( 263): d26 0000000000000000 d27 8080808080808080I/DEBUG ( 263): d28 0100010001000100 d29 0100010001000100I/DEBUG ( 263): d30 8080808080808080 d31 8080808080808080I/DEBUG ( 263): scr 60000010I/DEBUG ( 263): I/DEBUG ( 263): backtrace:I/DEBUG ( 263): #00 pc 00000bbe /data/app-lib/com.example.testjni-1/libjnitest.so (Java_com_example_testjni_MainActivity_add+5)I/DEBUG ( 263): #01 pc 0002044c /system/lib/libdvm.so (dvmPlatformInvoke+112)I/DEBUG ( 263): #02 pc 000512b3 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+398)I/DEBUG ( 263): #03 pc 0003b83d /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+8)I/DEBUG ( 263): #04 pc 00052cb5 /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+184)I/DEBUG ( 263): #05 pc 000298e0 /system/lib/libdvm.soI/DEBUG ( 263): #06 pc 00030e30 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)I/DEBUG ( 263): #07 pc 0002e4c8 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)I/DEBUG ( 263): #08 pc 00063a11 /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+392)I/DEBUG ( 263): #09 pc 0006b873 /system/lib/libdvm.soI/DEBUG ( 263): #10 pc 000298e0 /system/lib/libdvm.soI/DEBUG ( 263): #11 pc 00030e30 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)I/DEBUG ( 263): #12 pc 0002e4c8 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)I/DEBUG ( 263): #13 pc 0006372d /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+336)I/DEBUG ( 263): #14 pc 0004ce9b /system/lib/libdvm.soI/DEBUG ( 263): #15 pc 0003fe05 /system/lib/libdvm.soI/DEBUG ( 263): #16 pc 0004fb7f /system/lib/libandroid_runtime.soI/DEBUG ( 263): #17 pc 000508c5 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+388)I/DEBUG ( 263): #18 pc 0000105b /system/bin/app_processI/DEBUG ( 263): #19 pc 0000e593 /system/lib/libc.so (__libc_init+50)I/DEBUG ( 263): #20 pc 00000d7c /system/bin/app_processI/DEBUG ( 263): I/DEBUG ( 263): stack:I/DEBUG ( 263): be9b4278 be9b42e0 [stack]I/DEBUG ( 263): be9b427c 4009d49f /system/lib/libc.so (dlfree+50)I/DEBUG ( 263): be9b4280 400d6000 /system/lib/libc.soI/DEBUG ( 263): be9b4284 c31b3810 I/DEBUG ( 263): be9b4288 752e4840 I/DEBUG ( 263): be9b428c 00000000 I/DEBUG ( 263): be9b4290 00000000 I/DEBUG ( 263): be9b4294 00000000 I/DEBUG ( 263): be9b4298 00000000 I/DEBUG ( 263): be9b429c c31b3810 I/DEBUG ( 263): be9b42a0 41aab530 /dev/ashmem/dalvik-heap (deleted)I/DEBUG ( 263): be9b42a4 415e68f8 [heap]I/DEBUG ( 263): be9b42a8 415e69a0 [heap]I/DEBUG ( 263): be9b42ac 416a4c38 /system/lib/libdvm.soI/DEBUG ( 263): be9b42b0 df0027ad I/DEBUG ( 263): be9b42b4 00000000 I/DEBUG ( 263): #00 be9b42b8 41535c94 I/DEBUG ( 263): ........ ........I/DEBUG ( 263): #01 be9b42b8 41535c94 I/DEBUG ( 263): be9b42bc 00000001 I/DEBUG ( 263): be9b42c0 00000000 I/DEBUG ( 263): be9b42c4 41aab530 /dev/ashmem/dalvik-heap (deleted)I/DEBUG ( 263): be9b42c8 41aa3fa4 /dev/ashmem/dalvik-heap (deleted)I/DEBUG ( 263): be9b42cc 416382b7 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+402)I/DEBUG ( 263): #02 be9b42d0 41535c94 I/DEBUG ( 263): be9b42d4 7528331e /data/dalvik-cache/data@app@com.example.testjni-1.apk@classes.dexI/DEBUG ( 263): be9b42d8 752c9bb9 /data/app-lib/com.example.testjni-1/libjnitest.so (Java_com_example_testjni_MainActivity_add)I/DEBUG ( 263): be9b42dc 415e6908 [heap]I/DEBUG ( 263): be9b42e0 752e5b68 I/DEBUG ( 263): be9b42e4 752e5b70 I/DEBUG ( 263): be9b42e8 00000000 I/DEBUG ( 263): be9b42ec 00000000 I/DEBUG ( 263): be9b42f0 7179824c I/DEBUG ( 263): be9b42f4 400da394 I/DEBUG ( 263): be9b42f8 400d6000 /system/lib/libc.soI/DEBUG ( 263): be9b42fc 752e5bf1 I/DEBUG ( 263): be9b4300 752e5bf1 I/DEBUG ( 263): be9b4304 752e5b70 I/DEBUG ( 263): be9b4308 752e5bc0 I/DEBUG ( 263): be9b430c 00000000 I/DEBUG ( 263): ........ ........
adb logcat | $NDKROOT/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi
$NDKROOT/ndk-stack -sym obj/local/armeabi/ -dump exception.log
********** Crash dump: **********Build fingerprint: ‘test-keys'pid: 14337, tid: 14337, name: example.testjni >>> com.example.testjni <<<signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 752cb0fcStack frame #00 pc 00000bbe /data/app-lib/com.example.testjni-1/libjnitest.so (Java_com_example_testjni_MainActivity_add+5): Routine Java_com_example_testjni_MainActivity_add at /home/luohaitao/work/android/ndk/android-ndk-r9d/samples/testJNI/jni/com_example_testjni_MainActivity.cpp:6Stack frame #01 pc 0002044c /system/lib/libdvm.so (dvmPlatformInvoke+112)Stack frame #02 pc 000512b3 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+398)Stack frame #03 pc 0003b83d /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+8)Stack frame #04 pc 00052cb5 /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+184)Stack frame #05 pc 000298e0 /system/lib/libdvm.soStack frame #06 pc 00030e30 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)Stack frame #07 pc 0002e4c8 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)Stack frame #08 pc 00063a11 /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+392)Stack frame #09 pc 0006b873 /system/lib/libdvm.soStack frame #10 pc 000298e0 /system/lib/libdvm.soStack frame #11 pc 00030e30 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)Stack frame #12 pc 0002e4c8 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)Stack frame #13 pc 0006372d /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+336)Stack frame #14 pc 0004ce9b /system/lib/libdvm.soStack frame #15 pc 0003fe05 /system/lib/libdvm.soStack frame #16 pc 0004fb7f /system/lib/libandroid_runtime.soStack frame #17 pc 000508c5 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+388)Stack frame #18 pc 0000105b /system/bin/app_processStack frame #19 pc 0000e593 /system/lib/libc.so (__libc_init+50)Stack frame #20 pc 00000d7c /system/bin/app_process
更多相关文章
- android中ListActivity的使用
- Android深入浅出之Audio 第二部分 AudioFlinger分析
- Android(安卓)UI学习 - Menu
- Android(安卓)NDK开发指南---Android.mk文件
- 【android】类似微信底部按钮标签实现
- android之DEX文件格式
- Errors排解
- 如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接
- Android(安卓)JNI HelloWorld实现