In Android development, the program crash in three scenarios: Uncaught exception, ANR (application not responding), and flashback (Ndk throws an error). an uncaught exception in which the stack information printed according to Logcat is easy to locate the error. ANR Error Check, Android rules, when the app interacts with the user, if the user does not respond to the action within 5 seconds, a ANR error is raised, and a system prompt pops up to let the user choose to continue waiting or to close the program immediately. A traces.txt file is generated in the/DATA/ANR directory, which records the stack and thread information that the system generates the ANR exception. If this is a flashback , the problem is more difficult to find, usually in projects where the ndk throws some kind of fatal error causing a flashback. Because the NDK is developed using C/s + +, programmers familiar with C + + know that pointers and memory management are the most important and the most prone to problems, with a slight inadvertent encounter such as memory address access errors, use of wild targets, memory leaks, stack overflows, initialization errors, type conversion errors, The number of common problems, except for 0, leads to the same result: a program crashes. Does not pop up the "XXX program is unresponsive, closes immediately" prompt box like when the Java layer produces an exception. When the NDK error occurs, the Logcat print out of the heap of logs according to understand, and do not want to locate the source of the error from the log, let me often a bit crazy, furious, drink how many jdb are not working. When I tried to print the logs in each JNI function to track the problem, it was too inefficient and could not locate the problem. Good heavens have eyes, let me find the NDK provides several debugging tools to pinpoint the source of the error.
Three debugging tools are available in the NDK installation package: Addr2line, Objdump, and Ndk-stack, where Ndk-stack is placed in the $ndk_home directory, with the Ndk-build sibling directory. Addr2line and Objdump in the NDK cross compiler Toolchain directory, below is the directory structure of my native ndk cross compiler toolchain:
As you can see from the directory structure, the NDK implements multiple sets of identical tools for different CPU architectures. So when choosing the Addr2line and Objdump tools, choose based on the CPU architecture of your target machine. If it is an ARM architecture, select arm-linux-androidabi-4.6/4.8 (high version is generally selected). x86 architecture, select x86-4.6/4.8. Mipsel architecture, select mipsel-linux-android-4.6/4.8. If you do not know the CPU structure of the target machine, connect the phone to the computer and use the ADB shell Cat/proc/cpuinfo to view the CPU information of the phone. It's my native ARM architecture toolchain directory structure:
Here's a sample Hello-jni project to illustrate how to pinpoint errors with the NDK's own example
[CPP]View PlainCopy
- #include <string.h>
- #include <jni.h>
- Hell-jni.c
- #ifdef __cplusplus
- extern "C" {
- #endif
- void Willcrash ()
- {
- int i = 10;
- int y = i/0;
- }
- Jniexport jint jnicall jni_onload (javavm* vm, void* reserved)
- {
- Willcrash ();
- return jni_version_1_4;
- }
- Jstring
- Java_com_example_hellojni_hellojni_stringfromjni (jnienv* env,
- Jobject thiz)
- {
- //Omit implementation logic here ...
- }
- #ifdef __cplusplus
- }
- #endif
Line 7th defines a Willcrash function that has an illegal operation in addition to 0, which causes the program to crash. The 13th line of the Jni_onload function calls Willcrash, which is called back after Java loads the. So file, which means the program starts crashing. Here is the log that is printed after running the program:
[CPP]View PlainCopy
- 01-01 17:59:38.246:D/DALVIKVM (20794): late-enabling checkjni
- 01-01 17:59:38.246:i/activitymanager (1185):
- Start proc Com.example.hellojni for activity com.example.hellojni/. hellojni:pid=20794 uid=10351 gids={50351, 1028, 1015}
- 01-01 17:59:38.296:I/DALVIKVM (20794): Enabling JNI app bug Workarounds for target SDK version 3 ...
- 01-01 17:59:38.366:D/DALVIKVM (20794): Trying to load lib/data/app-lib/com.example.hellojni-1/libhello-jni.so 0x422a4f58
- 01-01 17:59:38.366:D/DALVIKVM (20794): Added gkfx lib/data/app-lib/com.example.hellojni-1/libhello-jni.so 0x422a4f58
- 01-01 17:59:38.366:a/libc (20794): Fatal signal 8 (SIGFPE) at 0x0000513a (code=-6), thread 20794 (XAMPLE.HELLOJNI)
- 01-01 17:59:38.476:i/debug (253): pid:20794, tid:20794, Name:xample.hellojni >>> com.example.hellojni << ;<
- 01-01 17:59:38.476:i/debug (253): Signal 8 (SIGFPE), code-6 (Si_tkill), fault addr 0000513a
- 01-01 17:59:38.586:i/debug (253): R0 00000000 R1 0000513a R2 00000008 R3 00000000
- 01-01 17:59:38.586:i/debug (253): R4 00000008 R5 0000000d R6 0000513a R7 0000010c
- 01-01 17:59:38.586:i/debug (253): R8 75226d08 R9 00000000 SL 417c5c38 FP bedbf134
- 01-01 17:59:38.586:i/debug (253): IP 41705910 sp bedbf0f0 lr 4012e169 pc 4013d10c CPSR 000f0010
- //Omit partial log ...
- 01-01 17:59:38.596:i/debug (253): BackTrace:
- 01-01 17:59:38.596:i/debug (253): #00 pc 0002210c/system/lib/libc.so (tgkill+12)
- 01-01 17:59:38.596:i/debug (253): #01 pc 00013165/system/lib/libc.so (pthread_kill+48)
- 01-01 17:59:38.596:i/debug (253): #02 pc 00013379/system/lib/libc.so (raise+10)
- 01-01 17:59:38.596:i/debug (253): #03 pc 00000e80/data/app-lib/com.example.hellojni-1/libhello-jni.so (__aeabi_idiv 0+8)
- 01-01 17:59:38.596:i/debug (253): #04 pc 00000cf4/data/app-lib/com.example.hellojni-1/libhello-jni.so (willCrash+32 )
- 01-01 17:59:38.596:i/debug (253): #05 pc 00000d1c/data/app-lib/com.example.hellojni-1/libhello-jni.so (JNI_OnLoad+2 0)
- 01-01 17:59:38.596:i/debug (253): #06 pc 00052eb1/system/lib/libdvm.so (dvmloadnativecode (char const*, Obje ct*, char**) +468)
- 01-01 17:59:38.596:i/debug (253): #07 pc 0006a62d/system/lib/libdvm.so
- 01-01 17:59:38.596:i/debug (253): //Omit partial log ...
- 01-01 17:59:38.596:i/debug (253): Stack:
- 01-01 17:59:38.596:i/debug (253): bedbf0b0 71b17034/system/lib/libsechook.so
- 01-01 17:59:38.596:i/debug (253): Bedbf0b4 7521ce28
- 01-01 17:59:38.596:i/debug (253): Bedbf0b8 71b17030/system/lib/libsechook.so
- 01-01 17:59:38.596:i/debug (253): BEDBF0BC 4012c3cf/system/lib/libc.so (DLFREE+50)
- 01-01 17:59:38.596:i/debug (253): bedbf0c0 40165000/system/lib/libc.so
- 01-01 17:59:38.596:i/debug (253): //Omit partial log ...
- 01-01 17:59:38.736:w/activitymanager (1185): Force finishing Activity com.example.hellojni/. Hellojni
Log analysis:
Line 3rd starts the app, line 5th tries to load the so in the application Data directory, and line 6th generates a fatal error when loading the so file, and the 7th line fatal signal 8 hints that this is a fatal error, the signal is issued by Linux, Signal 8 means that the floating-point arithmetic is abnormal, it should be done in the Willcrash function in addition to the 0 operation produced. The following focuses on the 15th row of backtrace logs, backtrace logs can be considered as the stack information of the JNI call, the "#两位数字 PC" begins with the BackTrace log. Note that line 20th and line 21 are our own compiled so file and defined two functions, where an exception is thrown, causing the program to crash .
[CPP]View PlainCopy
- 01-01 17:59:38.596:i/debug (253): #04 pc 00000cf4/data/app-lib/com.example.hellojni-1/libhello-jni.so (willCrash+32 )
- 01-01 17:59:38.596:i/debug (253): #05 pc 00000d1c/data/app-lib/com.example.hellojni-1/libhello-jni.so (JNI_OnLoad+2 0)
began to have some clues, but the specific collapse in the position of the two functions, we are not sure, if the function code is less good check, if more complex words, look up also laborious. This time we need to rely on the NDK to provide us with the tools to precisely locate. Before that, let's take a note of the assembly command address that let the program crash, willcrash:00000cf4,jni_onload:00000d1c
Method 1: Use Arm-linux-androideabi-addr2line to locate the error location
Take the ARM architecture CPU as an example and execute the following command:
[CPP]View PlainCopy
- /users/yangxin/documents/devtoos/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 _64/bin/arm-linux-androideabi-addr2line-e/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/ hello-jni/obj/local/armeabi-v7a/libhello-jni.so 00000CF4 00000d1c
-e: Specify the so file path
0000CF4 0000d1c: Assembly instruction Address of error
The results are as follows:
is not pleasantly surprised to see the results we want, respectively, in the HELLO-JNI.C 10 and 15 row of the wrong, and then go back to see the source of HELLO-JNI.C, 15 lines of jni_onload function within the call Willcrash functions, Line 10th does the crash caused by an operation other than 0.
Method 2: Use Arm-linux-androideabi-objdump to locate faulty function information
In the first way, through Addr2lin has gotten to the location of the code error, but do not know the function of the context information, it seems a little less "perfect" for me to pursue the ultimate, this is obviously not enough, let's look at how to locate the function information.
First, use the following command to export the function table information for so:
[CPP]View PlainCopy
- /users/yangxin/documents/devtoos/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 _64/bin/arm-linux-androideabi-objdump-s-d/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/ hello-jni/obj/local/armeabi-v7a/libhello-jni.so > Users/yangxin/desktop/dump.log
In the generated ASM file, locate the two wrong assembly instruction addresses that we started to locate (search for CF4 in the file or Willcrash can be found), as shown in:
In this way, you can also find out which function the two wrong pointer addresses are in.
Way 3:ndk-stack
If you feel that the above method is too cumbersome, ndk-stack can help you reduce the number of steps, directly to the location of the code error.
Real-time Analytics logs:
Use ADB to get the log of the Logcat and pass the pipeline output to the Ndk-stack analysis and specify the so file location that contains the symbol table. If your program contains multiple CPU architectures, you need to choose a different CPU architecture directory based on the CPU type of your phone. Take the ARMV7 architecture as an example and execute the following command:
[CPP]View PlainCopy
- ADB Logcat | ndk-stack-sym/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/hello-jni/obj/local/armeabi-v7a
When the program occurs crash, the following information is output:
[CPP]View PlainCopy
- pid:22654, tid:22654, Name:xample.hellojni >>> com.example.hellojni <<<
- Signal 8 (SIGFPE), code-6 (Si_tkill), fault addr 0000587e
- Stack frame #00 pc 0002210c/system/lib/libc.so (tgkill+12)
- Stack frame #01 pc 00013165/system/lib/libc.so (pthread_kill+48)
- Stack frame #02 pc 00013379/system/lib/libc.so (raise+10)
- Stack frame #03 pc 00000e80/data/app-lib/com.example.hellojni-1/libhello-jni.so (__aeabi_idiv0+8): Routine __aeabi_ Idiv0 at/s/ndk-toolchain/src/build/. /gcc/gcc-4.6/libgcc/. /gcc/config/arm/lib1funcs.asm:1270
- Stack frame #04 pc 00000cf4/data/app-lib/com.example.hellojni-1/libhello-jni.so (willcrash+32): Routine willcrash at/u Sers/yangxin/documents/devtoos/java/android-ndk-r9d/samples/hello-jni/jni/hello-jni.c:10
- Stack frame #05 pc 00000d1c/data/app-lib/com.example.hellojni-1/libhello-jni.so (jni_onload+20): Routine jni_onload at /users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/hello-jni/jni/hello-jni.c:15
- Stack frame #06 pc 00052eb1/system/lib/libdvm.so (dvmloadnativecode (char const*, object*, char**) +468)
- Stack Frame #07 pc 0006a62d/system/lib/libdvm.so
Lines 7th and 8th print out the error location in the source file, just as the addr2line results.
Get log re-analysis first:
This approach is similar to the one above, except that the source of the log is not the same. For apps or games to test the test department, the tester discovers crash, saves the log file with ADB Logcat, and sends it to the programmer for analysis through the Ndk-stack command. The operation flow is as follows:
[CPP]View PlainCopy
- ADB logcat > Crash.log
- NDK-STACK-SYM/USERS/YANGXIN/DOCUMENTS/DEVTOOS/JAVA/ANDROID-NDK-R9D/SAMPLES/HELLO-JNI/OBJ/LOCAL/ARMEABI-V7A- Dump Crash.log
The result is the same as the above method.
Transferred from: http://blog.csdn.net/xyang81/article/details/42319789
Android NDK development Crash error targeting