本文介绍一下用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


更多相关文章

  1. android中ListActivity的使用
  2. Android深入浅出之Audio 第二部分 AudioFlinger分析
  3. Android(安卓)UI学习 - Menu
  4. Android(安卓)NDK开发指南---Android.mk文件
  5. 【android】类似微信底部按钮标签实现
  6. android之DEX文件格式
  7. Errors排解
  8. 如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接
  9. Android(安卓)JNI HelloWorld实现

随机推荐

  1. android aidl 进程通信 调用错误
  2. android:screenOrientation 90,270设置
  3. Android(安卓)OpenGL ES 分析与实践
  4. Android-0.Android Studio布局中Relative
  5. Android的横竖屏切换
  6. Android Studio控件属性大全
  7. Android横竖屏总结
  8. Android编译过程详解(三)
  9. Android 单元测试之JUnit和Mockito
  10. ImageView下载图片加载