织梦CMS - 轻松建站从此开始!

罗索

当前位置: 主页>嵌入式开发>Android>

使用GDB调试JNI代码

落鹤生 发布于 2013-01-28 17:23 点击:次 
调试JNI的c/c++代码,我一直使用打印log的方式,费时费力。在网上搜索使用GDB调试JNI的文章也不多。后来在stackoverflow偶然看到ndk-gdb才知道自己把NDK的重要文档忽略了。于是赶快试验,没想到确实不难。现把使用方法记录下来。
TAG:

调试JNI的c/c++代码,我一直使用打印log的方式,费时费力。在网上搜索使用GDB调试JNI的文章也不多。后来在stackoverflow偶然看到ndk-gdb才知道自己把NDK的重要文档忽略了。于是赶快试验,没想到确实不难。现把使用方法记录下来。

NDK文档我总结了一下,有几方面需要了解:

● 使用方式
cd $PROJECT
$NDK/ndk-gdb

● 前提条件
- 必须使用 ndk-build 编译native代码;使用 make APP=<name> 是不行的
- AndroidManifest.xml 的 android:debuggable
- 使用Android 2.2+的设备或模拟器
- 使用Eclipse的话,ADT 0.9.7+
- 使用ant的话,Android 2.1 r2+ / 2.2 r1+

● ndk-gdb参数
--verbose        显示详细的会话启动信息。当不能启动GDB时,打开它可以得到更多帮助。
--force            如果存在了一个调试会话,先终止它,然后再启动自己。
--start            启动程序默认的activity,然后连接。默认是寻找系统中已经运行的程序。
--launch=<name>    指定要启动的activity,其它的和上面一样。
--launch-list    打印出可启动的所有activity。
--project=<path>    如果未进入项目目录而运行 ndk-gdb,必须使用该参数指明路径。
--port=<port>        默认使用TCP端口5039和程序通信。指定别的端口可以同时调试多个设备。
--adb=<file>    指明ADB的路径。最好把adb放到PATH环境变量里。
-d, -e, -s <serial>    调试设备?模拟器?或者指定号码(adb devices)
--exec=<file>
-x <file>        自定义一个初始化脚本,GDB每次启动都会调用。

● 只有Android 2.3的平台才能调试多线程。低版本的设备只能调试主线程。

下面是我调试JNI的步骤。

整个例子脱胎于NDK自带的hello-jni。

1. 先看java代码:

  1. public class HelloAndroid extends Activity 
  2.     private Button mButton; 
  3.     private TextView mText; 
  4.  
  5.     @Override 
  6.     public void onCreate(Bundle savedInstanceState) 
  7.     { 
  8.         super.onCreate(savedInstanceState); 
  9.         setContentView(R.layout.main); 
  10.  
  11.         mText = (TextView) findViewById(R.id.TVHelloAndroid); 
  12.         mButton = (Button) findViewById(R.id.button1); 
  13.  
  14.         mButton.setOnClickListener(new View.OnClickListener() 
  15.         { 
  16.             @Override 
  17.             public void onClick(View v) 
  18.             { 
  19.                 mText.setText(stringFromJNI()); 
  20.             } 
  21.         }); 
  22.     } 
  23.  
  24.     public native String stringFromJNI(); 
  25.  
  26.     static { 
  27.         System.loadLibrary("HelloAndroid-jni"); 
  28.     } 

2. 再看JNI代码-HelloAndroid-jni.cpp:

  1. #include <string> 
  2. #include <jni.h> 
  3. #include <android/log.h> 
  4. #include "util.h"       // 引用另外一个自定义模块的函数 
  5.  
  6. extern "C" { 
  7.  
  8. JNIEXPORT jstring JNICALL 
  9. Java_com_android_helloandroid_HelloAndroid_stringFromJNI( JNIEnv* env, jobject thiz ) 
  10.     int i = GetRandomInt(2, 10); 
  11.     std::string str(i, 'c'); 
  12.     str.append(", Hello Android from JNI"); 
  13.     return env->NewStringUTF(str.c_str()); 
  14.  

3. 上面的JNI代码中使用了另外一个JNI模块定义的函数GetRandomInt,其代码util.c为:

  1. #include <stdlib.h> 
  2.  
  3. /** 
  4.  * @return a random integer in [min, max]. 
  5.  */ 
  6. int GetRandomInt(int min, int max) 
  7.     return rand() % (max-min + 1) + min; 

4. 然后,把util.c这个模块编译成libutil.a,使用到的Android.mk和Application.mk文件如下示意:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := util
LOCAL_SRC_FILES := util.c
include $(BUILD_STATIC_LIBRARY)

APP_ABI := armeabi
APP_STL := gnustl_static

5. 然后把HelloAndroid-jni.cpp编译成最后的.so文件:

LOCAL_PATH := $(call my-dir)
TARGET_ARCH_ABI := armeabi

###################
#   prebuilt lib
###################
include $(CLEAR_VARS)

LOCAL_MODULE := util-prebuilt
LOCAL_SRC_FILES := ../../archive/util/obj/local/$(TARGET_ARCH_ABI)/libutil.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../archive/util/jni
include $(PREBUILT_STATIC_LIBRARY)

###################
#   final target
###################
include $(CLEAR_VARS)

LOCAL_MODULE := HelloAndroid-jni
LOCAL_SRC_FILES := HelloAndroid-jni.cpp
LOCAL_CFLAGS := -fsigned-char

# prebuilt
LOCAL_STATIC_LIBRARIES := util-prebuilt

LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

APP_STL := gnustl_static

6. 接下来就是编译、链接、安装apk文件了。注意,要安装到模拟器里。

7. 打开Cygwin的bash shell窗口,键入下面的命令:

export ANDROID_NDK_ROOT=/cygdrive/y/android_ndk_r5c

8. 最后键入下面的命令:

ndk-gdb --force --start -e

--force 表示关掉正在运行的实例

--start 表示启动新的实例

-e 表示使用模拟器

9. 等待十几秒钟,gdb会装入所有能找到的调试信息,最后出现gdb的提示符。成功!

使用ndk-gdb调试确实很简单。无需-g;自动寻找源文件;速度也可以。不足之处:若想在设备上使用,必须取得root权限才可。

(ba_jie)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201301/16493.html]
本文出处:CSDN博客 作者:ba_jie 原文
顶一下
(0)
0%
踩一下
(2)
100%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容