导航:首页 > 操作系统 > androidjnicrash

androidjnicrash

发布时间:2022-09-22 06:31:06

Ⅰ 如何定位android NDK开发中遇到的错误

NDK错误发生时,能拿到什么信息

利用Android

NDK开发本地应用的时候,几乎所有的程序员都遇到过程序崩溃的问题,但它的崩溃会在logcat中打印一堆看起来类似天书的堆栈信息,让人举足无措。单靠添加一行行的打印信息来定位错误代码做在的行数,无疑是一件令人崩溃的事情。在网上搜索“Android

NDK崩溃”,可以搜索到很多文章来介绍如何通过Android提供的工具来查找和定位NDK的错误,但大都晦涩难懂。下面以一个实际的例子来说明,首先生成一个错误,然后演示如何通过两种不同的方法,来定位错误的函数名和代码行。

首先,看在hello-jni程序的代码中做了什么(有关如何创建或导入工程,此处略):在JNI_OnLoad()的函数中,即so加载时,调用willCrash()函数,而在willCrash()函数中, std::string的这种赋值方法会产生一个空指针错误。这样,在hello-jni程序加载时就会闪退。我们记一下这两个行数:在61行调用了willCrash()函数;在69行发生了崩溃。

下面来看看发生崩溃(闪退)时系统打印的logcat日志:

[plain] view

plain

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

Build fingerprint: 'vivo/bbk89_cmcc_jb2/bbk89_cmcc_jb2:4.2.1/JOP40D/1372668680:user/test-keys'

pid: 32607, tid: 32607, name: xample.hellojni >>> com.example.hellojni <<<

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000

r0 00000000 r1 beb123a8 r2 80808080 r3 00000000

r4 5d635f68 r5 5cdc3198 r6 41efcb18 r7 5d62df44

r8 4121b0c0 r9 00000001 sl 00000000 fp beb1238c

ip 5d635f7c sp beb12380 lr 5d62ddec pc 400e7438 cpsr 60000010

backtrace:

#00 pc 00023438 /system/lib/libc.so

#01 pc 00004de8 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#02 pc 000056c8 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#03 pc 00004fb4 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#04 pc 00004f58 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#05 pc 000505b9 /system/lib/libdvm.so

#06 pc 00068005 /system/lib/libdvm.so

#07 pc 000278a0 /system/lib/libdvm.so

#08 pc 0002b7fc /system/lib/libdvm.so

#09 pc 00060fe1 /system/lib/libdvm.so

#10 pc 0006100b /system/lib/libdvm.so

#11 pc 0006c6eb /system/lib/libdvm.so

#12 pc 00067a1f /system/lib/libdvm.so

#13 pc 000278a0 /system/lib/libdvm.so

#14 pc 0002b7fc /system/lib/libdvm.so

#15 pc 00061307 /system/lib/libdvm.so

#16 pc 0006912d /system/lib/libdvm.so

#17 pc 000278a0 /system/lib/libdvm.so

#18 pc 0002b7fc /system/lib/libdvm.so

#19 pc 00060fe1 /system/lib/libdvm.so

#20 pc 00049ff9 /system/lib/libdvm.so

#21 pc 0004d419 /system/lib/libandroid_runtime.so

#22 pc 0004e1bd /system/lib/libandroid_runtime.so

#23 pc 00001d37 /system/bin/app_process

#24 pc 0001bd98 /system/lib/libc.so

#25 pc 00001904 /system/bin/app_process

stack:

beb12340 012153f8

beb12344 00054290

beb12348 00000035

beb1234c beb123c0 [stack]

……

如果看过logcat打印的NDK错误时的日志就会知道,这里省略了后面很多的内容,很多人看到这么多密密麻麻的日志就已经头晕脑胀了,即使是很多资深的Android开发者,在面对NDK日志时也大都默默的选择了无视

Ⅱ 如何分析,定位Android Native Crash

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。

[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]

Start procnet.coollet.infzmreader:umengService_v1 for service
net.coollet.infzmreader/com.umeng.message.

UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}

[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]

Turning on JNI app bug workarounds fortarget SDK version 8...

[ 12-09 21:39:35.611 21745:21745D/AgooService ]

onCreate()

我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。

在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。

同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。

另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。

了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。

Ⅲ android jni程序(c++)如何编译适用于arm-v8指令集的32位程序

可以看到Android上层的Application和ApplicationFramework都是使用java编写,

底层包括系统和使用众多的LIiraries都是C/C++编写的。

所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。

下面将学习Android是如何通过Jni来实现Java对C/C++函数的调用。以HelloWorld程序为例:

第一步:

使用Java编写HelloWorld 的Android应用程序:

package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("fresne", printJNI("I am HelloWorld Activity"));
}
static
{
//加载库文件
System.loadLibrary("HelloWorldJni");
}
//声明原生函数 参数为String类型 返回类型为String
private native String printJNI(String inputStr);
}

这一步我们可以使用eclipse来生成一个App;

因为eclipse会自动为我们编译此Java文件,后面要是用到。

第二步:

生成共享库的头文件:

进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/
下:

可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:

HelloWorld.class文件。

退回到classes一级目录:/HelloWorld/bin/classes/

执行如下命令

javah com.lucyfyr.HelloWorld

生成文件:com_lucyfyr_HelloWorld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif

可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI

Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;

java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。

当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。

第三步:

实现JNI原生函数源文件:

新建com_lucyfyr_HelloWorld.c文件:

#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/* Native interface, it will be call in java code */
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr)
{
LOGI("fresne Hello World From libhelloworld.so!");
// 从 instring 字符串取得指向字符串 UTF 编码的指针
const char *str =
(const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );
LOGI("fresne--->%s",(const char *)str);
// 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
(*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );
return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
/* This function will be call when the library first be load.
* You can do some init in the libray. return which version jni it support.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
void *venv;
LOGI("fresne----->JNI_OnLoad!");
if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("fresne--->ERROR: GetEnv failed");
return -1;
}
return JNI_VERSION_1_4;
}

OnLoadJava_com_lucyfyr_HelloWorld_printJNI

函数里面做一些log输出 注意JNI中的log输出的不同。

JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调,

这个函数里面可以进行一些初始化工作,比如注册函数映射表,缓存一些变量等,

最后返回当前环境所支持的JNI环境。本例只是简单的返回当前JNI环境。

http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html

Ⅳ 如何定位Android NDK开发中遇到的错误

Android NDK中的错误定位对很多开发者来说是一件头疼的事,本文通过一个Demo程序详细讲解了NDK的错误是如何产生的,以及如何通过命令行工具定位NDK的问题所在。

Android NDK是什么?

Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google称为“NDK”。众所周知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序。NDK包括:

从C / C++生成原生代码库所需要的工具和build files;

将一致的原生库嵌入可以在Android设备上部署的应用程序包文件(application packages files ,即.apk文件)中;

支持所有未来Android平台的一系列原生系统头文件和库。

为何要用到NDK?概括来说主要分为以下几种情况:

代码保护,由于APK的Java层代码很容易被反编译,而C/C++库反汇难度较大;

在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的;

便于移植,用C/C++写的库可以方便地在其他的嵌入式平台上再次使用。

Android JNI与NDK的关系

Java Native Interface(JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java代码能够与用其它编程语言(如C、C++和汇编语言)编写的应用程序和库进行交互操作。

简单来说,可以认为NDK就是能够方便快捷开发.so文件的工具。JNI的过程比较复杂,生成.so需要大量操作,而NDK的作用则是简化了这个过程。

哪些常见的NDK类型异常会导致程序Crash?

NDK编译生成的.so文件作为程序的一部分,在运行发生异常时同样会造成程序崩溃。不同于Java代码异常造成的程序崩溃,在NDK的异常发生时,程序在Android设备上都会立即退出,即通常所说的闪退,而不会弹出“程序xxx无响应,是否立即关闭”之类的提示框。

NDK是使用C/C++来进行开发的,熟悉C/C++的程序员都知道,指针和内存管理是最重要也是最容易出问题的地方,稍有不慎就会遇到诸如内存无效访问、无效对象、内存泄露、堆栈溢出等常见的问题,最后都是同一个结果:程序崩溃。例如我们常说的空指针错误,就是当一个内存指针被置为空(NULL)之后再次对其进行访问;另外一个经常出现的错误是,在程序的某个位置释放了某个内存空间,而后在程序的其他位置试图访问该内存地址,这就会产生无效地址错误。常见的错误类型如下:

初始化错误;

访问错误;

内存泄露;

参数错误;

堆栈溢出;

类型转换错误;

数字除0错误。

如何发现并解决NDK错误?

利用Android NDK开发本地应用时,几乎所有的程序员都遇到过程序崩溃的问题,但它的崩溃会在logcat中打印一堆看起来类似天书的堆栈信息,让人举足无措。单靠添加一行行的打印信息来定位错误代码做在的行数,无疑是一件令人崩溃的事情。在网上搜索“Android NDK崩溃”,可以搜索到很多文章来介绍如何通过Android提供的工具来查找和定位NDK的错误,但大都晦涩难懂。下面以一个实际的例子来说明,如何通过两种不同的方法,来定位错误的函数名和代码行。

首先,来看看我们在hello-jni程序的代码中做了什么(有关如何创建或导入工程,此处略),下面代码中:在JNI_OnLoad()的函数中,即so加载时,调用willCrash()函数,而在willCrash()函数中, std::string的这种赋值方法会产生一个空指针错误。这样,在hello-jni程序加载时就会闪退。我们记一下这两个行数:在61行调用了willCrash()函数;在69行发生了崩溃。

下面我们来看看发生崩溃(闪退)时系统打印的logcat日志:

如果你看过logcat打印的NDK错误的日志就会知道,我省略了后面很多的内容,很多人看到这么多密密麻麻的日志就已经头晕脑胀了,即使是很多资深的Android开发者,在面对NDK日志时也大都默默地选择了无视。

其实,只要你细心的查看,再配合Google 提供的工具,完全可以快速地准确定位出错的代码位置,这个工作我们称之为“符号化”。需要注意的是,如果要对NDK错误进行符号化的工作,需要保留编译过程中产生的包含符号表的so文件,这些文件一般保存在$PROJECT_PATH/obj/local/目录下。

第一种方法:ndk-stack

这个命令行工具包含在NDK工具的安装目录,和ndk-build及其他常用的一些NDK命令放在一起,比如在我的电脑上,其位置是/android-ndk-r9d/ndk-stack。根据Google官方文档,NDK从r6版本开始提供ndk-stack命令,如果你用的之前的版本,建议还是尽快升级至最新的版本。使用ndk –stack命令也有两种方式

实时分析日志

在运行程序的同时,使用adb获取logcat日志,并通过管道符输出给ndk-stack,同时需要指定包含符号表的so文件位置;如果你的程序包含了多种CPU架构,在这里需求根据错误发生时的手机CPU类型,选择不同的CPU架构目录,如:

Ⅳ 如何定位Android NDK开发中遇到的错误

1、首先,来看看在hello-jni程序的代码中做了什么(有关如何创建或导入工程,此处略),下面代码中:在JNI_OnLoad()的函数中,即so加载时,调用willCrash()函数,而在willCrash()函数中,std::string的这种赋值方法会产生一个空指针错误。这样,在hello-jni程序加载时就会闪退。记一下这两个行数:在61行调用了willCrash()函数;在69行发生了崩溃2、看看发生崩溃(闪退)时系统打印的logcat日志:只要细心的查看,再配合Google提供的工具,完全可以快速地准确定位出错的代码位置,这个工作我们称之为“符号化”。需要注意的是,如果要对NDK错误进行符号化的工作,需要保留编译过程中产生的包含符号表的so文件,这些文件一般保存在$PROJECT_PATH/obj/local/目录下。3方法:ndk-stack这个命令行工具包含在NDK工具的安装目录,和ndk-build及其他常用的一些NDK命令放在一起,比如在我的电脑上,其位置是/android-ndk-r9d/ndk-stack。根据Google官方文档,NDK从r6版本开始提供ndk-stack命令,如果你用的之前的版本,建议还是尽快升级至最新的版本。使用ndk–stack命令也有两种方式实时分析日志在运行程序的同时,使用adb获取logcat日志,并通过管道符输出给ndk-stack,同时需要指定包含符号表的so文件位置;如果你的程序包含了多种CPU架构,在这里需求根据错误发生时的手机CPU类型,选择不同的CPU架构目录,如:当崩溃发生时,会得到如下的信息:重点看一下#03和#04,这两行都是在我们自己生成的libhello-jni.so中的报错信息,因此会发现如下关键信息:回想一下之前代码,在JNI_OnLoad()函数中(第61行),调用了willCrash()函数;在willCrash()函数中(第69行),制造了一个错误。4先获取日志再分析这种方法其实和上面的方法没有什么大的区别,仅仅是logcat日志获取的方式不同。可以在程序运行的过程中将logcat日志保存到一个文件,甚至可以在崩溃发生时,快速的将logcat日志保存起来,然后再进行分析,比上面的方法稍微灵活一点,而且日志可以留待以后继续分析。

Ⅵ 如何分析android crash log

android framework分为java和native两层 native运行于C的runtime,高效。一般java层只是封装,通过jni访问native底层HAL,driver的crash也会导致上层的crash ‍ ,有效利用Log信息并对其进行分析与实时的监控管理,对于分析Android手机发生Crash的原因具有极为重要的作用。 Android Log 文件类型 由于Android上的应用程序千差万别,出现的问题也不尽相同。不过Bug类型还是有规律可循的,可以根据生成的Log文件找到相应的错误,通常错误信息里记录了错误的大致位置,据此可以捕获到问题的关键信息。 Log文件记录着每次操作的信息,在出现问题后可以借助log信息分析以达到解决问题的目的,Log文件类型主要分为以下几种: (1) Logcat: Main缓存日志,通过运行logcat命令,可以获得系统中使用的标记和优先级的列表,也可以加上过滤器进行表达式限制,只输出测试人员及研发人员感兴趣的标记-优先级组合。 …………………… (2) Bugreport: Java应用程序Crash时会产生一个Bugreport文件,该文件主要包括三个方面的内容: Dumpstate:内存信息,Cpu信息,Procrank信息,系统日志,Vm Trace信息等。 Build.Prop:当前版本、当前命令、显示系统Build的一些属性等; Dumpsys:Dump Of Service Meminfo(显示某个进程更详细的内存消耗情况以及Native And Java (Dalvik)堆栈的统计数) ; (3) Crashmp: 每次Crash都会产生一个Crashmp文件,文件包括主日志,Java 堆栈信息,本地调用堆栈,虚拟机/进程堆,Log缓存,内存信息,进程列表,Modem信息,Adb Log等信息; (4) Bratlog: 测试用例及详细信息; (5) Logalong: 事件,如手机通讯功能信息等; (6) Pullfs: Traces(Java 堆栈信息); (7) Procrank: Uss(Unique Set Size) 值,进程独自占用的物理内存。

Ⅶ 最近在做android开发,最后时候无法启动,有没有大神能帮我分析一下这个日志 我到底错在哪里

那些省电软件只是关掉运行的软件来省电。但有很多软件是自动后台启动,关了会自己打开,所以省电王没用,加上省电王要运行,自然更费电了。建议你下个lbe安全大师,获得权限,关闭不需要的软件自动启用。

Ⅷ android中的native crash指的是什么大概有几种情况

android framework分为java和native两层
native运行于C的runtime,高效。一般java层只是封装,通过jni访问native底层HAL,driver的crash也会导致上层的crash ‍
,有效利用Log信息并对其进行分析与实时的监控管理,对于分析Android手机发生Crash的原因具有极为重要的作用。
Android Log 文件类型
由于Android上的应用程序千差万别,出现的问题也不尽相同。不过Bug类型还是有规律可循的,可以根据生成的Log文件找到相应的错误,通常错误信息里记录了错误的大致位置,据此可以捕获到问题的关键信息。
Log文件记录着每次操作的信息,在出现问题后可以借助log信息分析以达到解决问题的目的,Log文件类型主要分为以下几种:
(1) Logcat: Main缓存日志,通过运行logcat命令,可以获得系统中使用的标记和优先级的列表,也可以加上过滤器进行表达式限制,只输出测试人员及研发人员感兴趣的标记-优先级组合。
……………………
(2) Bugreport: Java应用程序Crash时会产生一个Bugreport文件,该文件主要包括三个方面的内容:

Dumpstate:内存信息,Cpu信息,Procrank信息,系统日志,Vm Trace信息等。
Build.Prop:当前版本、当前命令、显示系统Build的一些属性等;
Dumpsys:Dump Of Service Meminfo(显示某个进程更详细的内存消耗情况以及Native And Java (Dalvik)堆栈的统计数) ;
(3) Crashmp: 每次Crash都会产生一个Crashmp文件,文件包括主日志,Java 堆栈信息,本地调用堆栈,虚拟机/进程堆,Log缓存,内存信息,进程列表,Modem信息,Adb Log等信息;
(4) Bratlog: 测试用例及详细信息;
(5) Logalong: 事件,如手机通讯功能信息等;
(6) Pullfs: Traces(Java 堆栈信息);
(7) Procrank: Uss(Unique Set Size) 值,进程独自占用的物理内存。
转载

阅读全文

与androidjnicrash相关的资料

热点内容
appstore中的钱怎么退 浏览:495
单片机程序下载后如何运行 浏览:475
刚买的阿里云服务器怎样搭建网站 浏览:637
公园设计pdf 浏览:684
缓解压力最好的办法美国 浏览:387
前后端系统数据加密解密 浏览:194
中国移动营业app怎么看套餐 浏览:205
javastatic数组 浏览:950
需要会员管理源码 浏览:415
手机app如何解除加密 浏览:167
用云服务器还得买个瘦主机 浏览:728
如何查看办公电脑服务器地址 浏览:368
海星云的服务器是什么系统 浏览:411
抖音小笼包解压神器 浏览:558
手机下载的源码在哪里储存 浏览:846
pdf看三维 浏览:406
九宫算法干什么用的 浏览:907
phpjava性能比较 浏览:886
2016会计中级pdf 浏览:181
农村信用社app怎么删除明细 浏览:818