如何读懂和分析Android的logcat以及stack traces

作者&投稿:秋缸 (若有异议请与网页底部的电邮联系)
请教如何分析ANR的traces.txt-Android新手入门~

一:什么是ANR
ANR:Application Not Responding,即应用无响应
二:ANR的类型
ANR一般有三种类型:
1:KeyDispatchTimeout(5 seconds) --主要类型
按键或触摸事件在特定时间内无响应
2:BroadcastTimeout(10 seconds)
BroadcastReceiver在特定时间内无法处理完成

首先,让我们看一看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放到一起看。

不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。

AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。

Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:

I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:
pid=1760 uid=10065 gids={50065, 1028}

D/AndroidRuntime( 1760): Shutting downVM

W/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)

E/AndroidRuntime( 1760): FATALEXCEPTION: main

E/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo
{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerException

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)

E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)

E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)

E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
(ZygoteInit.java:793)

E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)

E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)

E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerException

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)

E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)

E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)

E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)

E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)

E/AndroidRuntime( 1760): ... 11more

I/Process ( 1760): Sending signal.PID: 1760 SIG: 9

W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivity

Jave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:

F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)

D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36ms

I/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocation

D/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34ms

I/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******

I/DEBUG ( 127):Build fingerprint:
'Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys'

I/DEBUG ( 127):Revision: '9'

I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<
I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000

I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000

I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2c

I/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1c

I/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030

I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8

I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08

I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8

I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78

I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000

I/DEBUG ( 127): d10 0000000000000000 d110000000000000000

I/DEBUG ( 127): d120000000000000000 d130000000000000000

I/DEBUG ( 127): d14 0000000000000000 d150000000000000000

I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fc

I/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000

I/DEBUG ( 127): d20 0000000000000000 d210000000000000000

I/DEBUG ( 127): d22 0000000000000000 d230000000000000000

I/DEBUG ( 127): d24 0000000000000000 d250000000000000000

I/DEBUG ( 127): d26 0000000000000000 d270000000000000000

I/DEBUG ( 127): d28 0000000000000000 d290000000000000000

I/DEBUG ( 127): d30 0000000000000000 d310000000000000000

I/DEBUG ( 127): scr 00000010

I/DEBUG ( 127):

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

I/DEBUG ( 127):

I/DEBUG ( 127):stack:

I/DEBUG ( 127): beb4aaa8 000000c8
I/DEBUG ( 127): beb4aaac 00000000
I/DEBUG ( 127): beb4aab0 00000000
I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linker

I/DEBUG ( 127): beb4aab8 00001000
I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)

I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testapp

I/DEBUG ( 127): beb4aac8 00000000
I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testapp

I/DEBUG ( 127): beb4aad0 beb4ab24 [stack]

I/DEBUG ( 127): beb4aad4 00000001
I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]

I/DEBUG ( 127): beb4aadc 00000000
I/DEBUG ( 127): beb4aae0 df0027ad
I/DEBUG ( 127): beb4aae4 00000000
I/DEBUG ( 127): #00 beb4aae8 00000000
I/DEBUG ( 127): ........ ........

I/DEBUG ( 127): #01 beb4aae8 00000000
I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)

I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]

I/DEBUG ( 127): beb4aaf4 00000000
I/DEBUG ( 127): beb4aaf8 00000000
I/DEBUG ( 127): beb4aafc 00000000
I/DEBUG ( 127): beb4ab00 00000000
I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testapp

I/DEBUG ( 127):


这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:

pid: 2102, tid: 2102,name: testapp >>>./testapp <<<
从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。

接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:

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

signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。

再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:

I/DEBUG ( 127):backtrace:

I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp

I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp

I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)

I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp

因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:

#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e

参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:

memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108

剩余三个地址翻译如下:

main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38

out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361

_start libgcc2.c:0

利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。

了解了如何分析普通的Log文件,下面让我们再看看如何分析ANR的Log文件。

  一般在平时工作中,基本上很多代码可以在eclipse+ndk进行调试,但如果需要用到具体的硬件设备,如媒体播放设备无法模拟的情况下,只能上硬件(盒子或手机)上进行调试。此时唯一的调试手段就是logcat产生log信息进行分析问题了。
  什么时候会有Log文件的产生 ?一般在如下几种情况会产生log文件 。
  1、程序异常退出 uncaused exception
  2、程序强制关闭 Force Closed (简称FC)
  3、程序无响应 Application No Response(简称ANR),一般主线程超过5秒么有处理就会ANR
  4、手动生成
  进入控制台输入:logcat命令即可进行输出
  第一部分
  1、分析工具介绍
  a、cat /proc/meminfo 显示基本的内存信息
  ------ MEMORY INFO (/proc/meminfo) ------
  MemTotal: 285184 kB
  MemFree: 106360 kB
  Buffers: 0 kB
  Cached: 60036 kB
  SwapCached: 0 kB
  Active: 98160 kB
  Inactive: 49100 kB
  Active(anon): 87260 kB
  Inactive(anon): 288 kB
  Active(file): 10900 kB
  Inactive(file): 48812 kB
  Unevictable: 0 kB
  Mlocked: 0 kB
  SwapTotal: 0 kB
  SwapFree: 0 kB
  Dirty: 0 kB
  Writeback: 0 kB
  AnonPages: 87240 kB
  Mapped: 26500 kB
  Shmem: 324 kB
  Slab: 13340 kB
  SReclaimable: 1672 kB
  SUnreclaim: 11668 kB
  KernelStack: 2160 kB
  PageTables: 5600 kB
  NFS_Unstable: 0 kB
  Bounce: 0 kB
  WritebackTmp: 0 kB
  CommitLimit: 142592 kB
  Committed_AS: 1065600 kB
  VmallocTotal: 417792 kB
  VmallocUsed: 137700 kB
  VmallocChunk: 254980 kB
  重点关注这下面几个值:
  MemTotal: 285184 kB //总计物理内存的大小
  MemFree: 106360 kB //可用内存有多少
  Buffers: 0 kB //磁盘缓存内存的大小
  Cached: 60036 kB
  # free
  free
  total used free shared buffers
  Mem: 285184 178884 106300 0 0
  Swap: 0 0 0
  Total: 285184 178884 106300
  在linux中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。
  但实际上这些内存也是可以立刻拿来使用的。
  所以空闲内存=free+buffers+cached=total-used
  还有几个命令可使用:
  /proc/meminfo 机器的内存使用信息
  /proc/pid/maps pid为进程号,显示当前进程所占用的虚拟地址。
  /proc/pid/statm 进程所占用的内存
  b、查看进程信息
  ------ CPU INFO (top -n 1 -d 1 -m 30 -t) ------
  能够实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器
  c、android提供的一些操作工具
  ------ PROCRANK (procrank) ------
  ------ PROCMEM (procmem) ------
  ------ SHOWMAP (showmap) ------
  ... 就不一一列举了,有兴趣的朋友可以去看看
  这此工具的代码位于android的 /system/extras
  d、虚拟内存的查看工具
  ------ VIRTUAL MEMORY STATS (/proc/vmstat) ------
  ------ VMALLOC INFO (/proc/vmallocinfo) ------
  2、时间信息,也是我们主要分析的信息
  格式如下:
  ------ SYSTEM LOG (logcat -b system -v time -d *:v) ------
  $:logcat -b system -v time -d *:v
  01-02 08:00:02.570 I/SystemServer( 957): Notification Manager
  01-02 08:00:02.570 I/SystemServer( 957): Device Storage Monitor
  01-02 08:00:02.580 I/SystemServer( 957): Location Manager
  01-02 08:00:02.580 I/SystemServer( 957): Search Service
  01-02 08:00:02.590 I/SystemServer( 957): DropBox Service
  01-02 08:00:02.590 I/SystemServer( 957): Wallpaper Service
  3、虚拟机信息,包括进程的,线程的跟踪信息,这是用来跟踪进程和线程具体点的好地方 。
  ------ VM TRACES JUST NOW (/data/anr/traces.txt.bugreport: 2011-01-15 16:49:02) ------
  ------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2011-01-15 16:49:02) ------
  格式如下 :
  ----- pid 1516 at 1970-01-02 08:03:07 -----
  Cmd line: com.ipanel.join.appstore
  DALVIK THREADS:
  (mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
  "main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x4001f188 self=0xd028
  | sysTid=1516 nice=0 sched=3/0 cgrp=[fopen-error:2] handle=-1345017744
  第二部分
  如何分析log信息
  1、查找错误信息的关键字眼
  "error" "failxx" "E/" 等的错误信息
  将这些问题先行解决掉
  2、动态库死机
  查看类似的“Build fingerprint:”这些关键字
  I/DEBUG ( 692): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  I/DEBUG ( 692): Build fingerprint: 'generic/generic/generic:2.3.1/GRH78/eng.userdev-rd6-input.20120221.113348:eng/test-keys'
  I/DEBUG ( 692): pid: 694, tid: 694 >>> /system/bin/mediaserver <<<
  I/DEBUG ( 692): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000input module init -->
  010
  对于这此信息,可以查看动态库的分析:
  http://blog.csdn.net/andyhuabing/article/details/7074979
  3、解决java抛异常的问题解决
  E/UsbObserver( 957): java.lang.NullPointerException
  E/UsbObserver( 957): at com.android.server.UsbObserver.init(UsbObserver.java:131)
  E/UsbObserver( 957): at com.android.server.UsbObserver.<init>(UsbObserver.java:65)
  E/UsbObserver( 957): at com.android.server.ServerThread.run(SystemServer.java:419)
  I/SystemServer( 957): UI Mode Manager Service
  这个直接找到java代码,分析其实现即可解决
  4、ANR问题
  搜索“ANR”关键词,快速定位到关键事件信息 。
  定位到关键的事件信息如下:
  I/dalvikvm( 1014): Wrote stack traces to '/data/anr/traces.txt'
  I/Process ( 957): Sending signal. PID: 1124 SIG: 9

  指定哪个java包出问题
  E/ActivityManager( 957): ANR in com.ipanel.join.appstore
  进程号为957发生了如下错误:com.ipanel.join.appstore 包下面 Broadcast问题
  ANR原因:
  E/ActivityManager( 957): Reason: Broadcast of Intent { act=android.appwidget.action.APPWIDGET_UPDATE cmp=com.ipanel.join.appstore/.widget.SmallWidget1 (has extras) }
  这是ANR的堆栈调用文件
  I/dalvikvm( 1014): Wrote stack traces to '/data/anr/traces.txt'
  通过上面的log信息分析,应该是接收一个广播消息时超时了
  我们再分析虚拟机信息 ,打开/data/anr/traces.txt,可有通过adb pull /data/anr/traces.txt .
  这里每一段都是一个线程 ,当然我们还是看线程号为1的主线程了。通过分析发现关键问题是这样:
  搜索“DALVIK THREADS”关键词,快速定位到本应用程序的虚拟机信息日志
  ----- pid 1516 at 1970-01-02 08:03:07 -----
  Cmd line: com.ipanel.join.appstore
  DALVIK THREADS:
。。。
  at com.ipanel.join.appstore.widget.AbsSmallWidget.getRemoteViews(AbsSmallWidget.java:56)
  其实从这句话:
  at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
  基本上确认是 socket ->connect 连接超时了,导致主线程5s内没有响应从而产生ANR错误。默认的connect连接timeout时间是75s
  其实解决办法就是利用非阻塞方式进行连接即可。
  从CPU占用率上也可以看出是在kernel中执行堵塞住了
  E/ActivityManager( 957): 75% TOTAL: 4.7% user + 70% kernel
  5、执行DexOpt错误
  W/dalvikvm( 1803): DexOpt: --- END 'SettingsProvider.apk' --- status=0x000a, process failed
  E/dalvikvm( 1803): Unable to extract+optimize DEX from '/system/app/SettingsProvider.apk'
。。。。android.app.ActivityThread.installProvider(ActivityThread.java:3557)

  E/SystemServer( 1803): at android.app.ActivityThread.getProvider(ActivityThread.java:3356)
  从上面的打印看,是在解压或优化extract+optimize DEX的apk文件时出错了
  1、没有出现magic number错误,这个原因与原子操作无关(这是一快速的加锁和解锁的轻量级操作函数)
  2、执行dexopt出错
  查明是服务器硬盘没空间了,导致引导文件系统的时候没有空间进行解压而失败
  6、系统启动后默认其妙或随机死机情况
  出现这种错误:
  12-01 08:11:56.027: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:11:57.315: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:11:59.318: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:03.332: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:05.329: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:07.216: WARN/KeyCharacterMap(312): No keyboard for id 0
  12-01 08:12:07.216: WARN/KeyCharacterMap(312): Using default keymap: /system/usr/keychars/qwerty.kcm.bin

基本上很多代码可以在eclipse+ndk进行调试,但如果需要用到具体的硬件设备,如媒体播放设备无法模拟的情况下,只能上硬件(盒子或手机)上进行调试。此时唯一的调试手段就是logcat产生log信息进行分析问题了。
  什么时候会有Log文件的产生 ?一般在如下几种情况会产生log文件 。
  1、程序异常退出 uncaused exception
  2、程序强制关闭 Force Closed (简称FC)
  3、程序无响应 Application No Response(简称ANR),一般主线程超过5秒么有处理就会ANR
  4、手动生成
  进入控制台输入:logcat命令即可进行输出
  第一部分
  1、分析工具介绍
  a、cat /proc/meminfo 显示基本的内存信息
  ------ MEMORY INFO (/proc/meminfo) ------
  MemTotal: 285184 kB
  MemFree: 106360 kB
  Buffers: 0 kB
  Cached: 60036 kB
  SwapCached: 0 kB
  Active: 98160 kB
  Inactive: 49100 kB
  Active(anon): 87260 kB
  Inactive(anon): 288 kB
  Active(file): 10900 kB
  Inactive(file): 48812 kB
  Unevictable: 0 kB
  Mlocked: 0 kB
  SwapTotal: 0 kB
  SwapFree: 0 kB
  Dirty: 0 kB
  Writeback: 0 kB
  AnonPages: 87240 kB
  Mapped: 26500 kB
  Shmem: 324 kB
  Slab: 13340 kB
  SReclaimable: 1672 kB
  SUnreclaim: 11668 kB
  KernelStack: 2160 kB
  PageTables: 5600 kB
  NFS_Unstable: 0 kB
  Bounce: 0 kB
  WritebackTmp: 0 kB
  CommitLimit: 142592 kB
  Committed_AS: 1065600 kB
  VmallocTotal: 417792 kB
  VmallocUsed: 137700 kB
  VmallocChunk: 254980 kB
  重点关注这下面几个值:
  MemTotal: 285184 kB //总计物理内存的大小
  MemFree: 106360 kB //可用内存有多少
  Buffers: 0 kB //磁盘缓存内存的大小
  Cached: 60036 kB
  # free
  free
  total used free shared buffers
  Mem: 285184 178884 106300 0 0
  Swap: 0 0 0
  Total: 285184 178884 106300
  在linux中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。
  但实际上这些内存也是可以立刻拿来使用的。
  所以空闲内存=free+buffers+cached=total-used
  还有几个命令可使用:
  /proc/meminfo 机器的内存使用信息
  /proc/pid/maps pid为进程号,显示当前进程所占用的虚拟地址。
  /proc/pid/statm 进程所占用的内存
  b、查看进程信息
  ------ CPU INFO (top -n 1 -d 1 -m 30 -t) ------
  能够实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器
  c、android提供的一些操作工具
  ------ PROCRANK (procrank) ------
  ------ PROCMEM (procmem) ------
  ------ SHOWMAP (showmap) ------
  ... 就不一一列举了,有兴趣的朋友可以去看看
  这此工具的代码位于android的 /system/extras
  d、虚拟内存的查看工具
  ------ VIRTUAL MEMORY STATS (/proc/vmstat) ------
  ------ VMALLOC INFO (/proc/vmallocinfo) ------
  2、时间信息,也是我们主要分析的信息
  格式如下:
  ------ SYSTEM LOG (logcat -b system -v time -d *:v) ------
  $:logcat -b system -v time -d *:v
  01-02 08:00:02.570 I/SystemServer( 957): Notification Manager
  01-02 08:00:02.570 I/SystemServer( 957): Device Storage Monitor
  01-02 08:00:02.580 I/SystemServer( 957): Location Manager
  01-02 08:00:02.580 I/SystemServer( 957): Search Service
  01-02 08:00:02.590 I/SystemServer( 957): DropBox Service
  01-02 08:00:02.590 I/SystemServer( 957): Wallpaper Service
  3、虚拟机信息,包括进程的,线程的跟踪信息,这是用来跟踪进程和线程具体点的好地方 。
  ------ VM TRACES JUST NOW (/data/anr/traces.txt.bugreport: 2011-01-15 16:49:02) ------
  ------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2011-01-15 16:49:02) ------
  格式如下 :
  ----- pid 1516 at 1970-01-02 08:03:07 -----
  Cmd line: com.ipanel.join.appstore
  DALVIK THREADS:
  (mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
  "main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x4001f188 self=0xd028
  | sysTid=1516 nice=0 sched=3/0 cgrp=[fopen-error:2] handle=-1345017744
  第二部分
  如何分析log信息
  1、查找错误信息的关键字眼
  "error" "failxx" "E/" 等的错误信息
  将这些问题先行解决掉
  2、动态库死机
  查看类似的“Build fingerprint:”这些关键字
  I/DEBUG ( 692): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  I/DEBUG ( 692): Build fingerprint: 'generic/generic/generic:2.3.1/GRH78/eng.userdev-rd6-input.20120221.113348:eng/test-keys'
  I/DEBUG ( 692): pid: 694, tid: 694 >>> /system/bin/mediaserver <<<
  I/DEBUG ( 692): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000input module init -->
  010
  对于这此信息,可以查看动态库的分析:
  http://blog.csdn.net/andyhuabing/article/details/7074979
  3、解决java抛异常的问题解决
  E/UsbObserver( 957): java.lang.NullPointerException
  E/UsbObserver( 957): at com.android.server.UsbObserver.init(UsbObserver.java:131)
  E/UsbObserver( 957): at com.android.server.UsbObserver.<init>(UsbObserver.java:65)
  E/UsbObserver( 957): at com.android.server.ServerThread.run(SystemServer.java:419)
  I/SystemServer( 957): UI Mode Manager Service
  这个直接找到java代码,分析其实现即可解决
  4、ANR问题
  搜索“ANR”关键词,快速定位到关键事件信息 。
  定位到关键的事件信息如下:
  I/dalvikvm( 1014): Wrote stack traces to '/data/anr/traces.txt'
  I/Process ( 957): Sending signal. PID: 1124 SIG: 9

  指定哪个java包出问题
  E/ActivityManager( 957): ANR in com.ipanel.join.appstore
  进程号为957发生了如下错误:com.ipanel.join.appstore 包下面 Broadcast问题
  ANR原因:
  E/ActivityManager( 957): Reason: Broadcast of Intent { act=android.appwidget.action.APPWIDGET_UPDATE cmp=com.ipanel.join.appstore/.widget.SmallWidget1 (has extras) }
  这是ANR的堆栈调用文件
  I/dalvikvm( 1014): Wrote stack traces to '/data/anr/traces.txt'
  通过上面的log信息分析,应该是接收一个广播消息时超时了
  我们再分析虚拟机信息 ,打开/data/anr/traces.txt,可有通过adb pull /data/anr/traces.txt .
  这里每一段都是一个线程 ,当然我们还是看线程号为1的主线程了。通过分析发现关键问题是这样:
  搜索“DALVIK THREADS”关键词,快速定位到本应用程序的虚拟机信息日志
  ----- pid 1516 at 1970-01-02 08:03:07 -----
  Cmd line: com.ipanel.join.appstore
  DALVIK THREADS:
。。。
  at com.ipanel.join.appstore.widget.AbsSmallWidget.getRemoteViews(AbsSmallWidget.java:56)
  其实从这句话:
  at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
  基本上确认是 socket ->connect 连接超时了,导致主线程5s内没有响应从而产生ANR错误。默认的connect连接timeout时间是75s
  其实解决办法就是利用非阻塞方式进行连接即可。
  从CPU占用率上也可以看出是在kernel中执行堵塞住了
  E/ActivityManager( 957): 75% TOTAL: 4.7% user + 70% kernel
  5、执行DexOpt错误
  W/dalvikvm( 1803): DexOpt: --- END 'SettingsProvider.apk' --- status=0x000a, process failed
  E/dalvikvm( 1803): Unable to extract+optimize DEX from '/system/app/SettingsProvider.apk'
。。。。android.app.ActivityThread.installProvider(ActivityThread.java:3557)

  E/SystemServer( 1803): at android.app.ActivityThread.getProvider(ActivityThread.java:3356)
  从上面的打印看,是在解压或优化extract+optimize DEX的apk文件时出错了
  1、没有出现magic number错误,这个原因与原子操作无关(这是一快速的加锁和解锁的轻量级操作函数)
  2、执行dexopt出错
  查明是服务器硬盘没空间了,导致引导文件系统的时候没有空间进行解压而失败
  6、系统启动后默认其妙或随机死机情况
  出现这种错误:
  12-01 08:11:56.027: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:11:57.315: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:11:59.318: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:03.332: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:05.329: WARN/SharedBufferStack(312): waitForCondition(LockCondition) timed out (identity=19, status=0). CPU may be pegged. trying again.
  12-01 08:12:07.216: WARN/KeyCharacterMap(312): No keyboard for id 0
  12-01 08:12:07.216: WARN/KeyCharacterMap(312): Using default keymap: /system/usr/keychars/qwerty.kcm.bin


如何分析一篇英语文章?
面包广泛消费),如果大家省略的话,通常都省略副词widely,省略后就变成了消费不消费面包,整个意思就变了,过多的做句子的结构分析有时可造成读错原文,导致丢分,因此,我们在英语考试时,即得抓住意思,抛掉结构分析,一句话读下来即可。 2、快速读懂阅读文文章方向(篇章性能力main idea),放弃细节 ...

做英语阅读理解题和改错题的技巧有哪些???
解题方法:读懂原文,抓住关键词、短语、句子或段落,透彻理解文章内容,注意文章结构层次和逻辑关系,仔细斟酌,作出准确的推断和引申。(四)主旨大意题此类题主要针对的主题、中心思想、主题句或主题段、作者的写作目的(purpose)等方面,要求考生在准确理解全文后归纳短文要点、概括中心思想,也分析和归纳段落...

托福宝宝最想问的问题:托福阅读长难句如何读懂?
分析:此句为简单句:主语+谓语+宾语。主语为the topics, included 是谓语,discussed是过去分词作后置定语,the coordinated study of the destruction of forests和how to combat forest fires, the extension of European research programs on the forest ecosystem是有as well as, and连接的三个并列宾...

如何读懂听力中句子和单词的重音
不规则形式的正则化也缓慢地继续,并且变形形式的分析替代方法变得越来越普遍。受美式英语在媒体中的强大影响以及与美国作为世界大国相关的声望,英式英语也在美式英语的影响下也在发生变化。 不规则形式的正则化也缓慢地继续,并且变形形式的分析替代方法变得越来越普遍。受美式英语在媒体中的强大影响以及与美国作为世界大...

高中英语阅读需要掌握的技巧和方法
高中英语阅读要掌握的方法与技巧(二) 一、英语阅读中的三大障碍 1.语言的障碍。Readingis a comprehensive skill because it concerns the recognition of configuration, pronunciation, grammatical inflexion and the comprehension of words, sentences and paragraphs.(魏立明,孙长顺:2001 )由于有的单词往往有几种甚至...

如何读懂中国经济的现状与改革前景
在分析国民资产负债表的债务状况时,通常使用有两个指标:一个是债务率(债务对总资产的比例),另一个是杠杆率(债务对GDP的比例)。一般认为中国现在总的杠杆率大概在300%左右,即我国一年的经济增量的3倍。杠杆率(债务对GDP比率)加速提高,来源:McKinsey Global Institute: 《Debt and (not much)...

雅思阅读 如何读懂论证类说明文的文章结构
二、识别并读懂文章中的主要论述观点 Identify and follow key arguments in a text 这种雅思阅读技能是指从整体去把握一篇文章的结构,并对相应的重要的文章观点进行提炼理解的能力。雅思的阅读文章比较学术性,所以相对与其他的文体而言结构其实是比较容易把握的。但还是需要经过真题文章的仔细分析体会去学习...

如何提高理解英语文章隐含的意思
分析:这是一道推理判断的深层理解题。题目意为:"Vauvenarges'评论表明了…"。应从第三段最后一句话" All men are born truthful and die liars."在文章中加以分析判断,方能得出正确结论。B项具有干扰性,因为它表达这样一个含义,即"不诚实随着年龄的增长而增长"。但从整段的理解中,特别是作者引用该哲学家的...

托福阅读之”为什么‘读懂了’却做不对题”
从下面的例子中来分析一下吧!首先说一下所谓的”文章已经读懂了”,有时,这个读懂只是感觉读懂,但实际并未读懂。The water was always laden with pebbles, gravel, and sand, known as glacial outwash, that was deposited as the flow slowed down. (TPO1-Groundwater)The phrase “glacial outwash” in ...

sat阅读中怎样读懂复杂句的结构
你好,关于sat阅读中怎样读懂复杂句的结构?一般我们说长难句的时候,首先想到的就是4,5行左右的看着巨痛苦无比的句子,很多书里讲这些句子做了分类,一般难句归结为复杂修饰成分,大段插入语,重要修饰成分后置,省略。但是我们仔细分析会发现这些句子无论再怎么分类,对于我们看来就是两个特点:长,...

美溪区13368048926: Eclipse如何解析Android url -
寇虾盐酸: URL的操作具体如下://初始化一个URL对象URL url = new URL(data);//获得HTTPConnection网络连接对象HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(5*1000);connection....

美溪区13368048926: 如何分析Android的Log -
寇虾盐酸: :通过log不容易,加些时间,可能会有启发,再分析下代码,可能问题1)多个线程之间的问题.2)资源的问题,APP在android是优先级比较低的.换个高端客户端试试...

美溪区13368048926: android中looper的实现原理,为什么调用looper.prepare就在当前线程关联了一个lo -
寇虾盐酸: Looper.prepare()方法在当前线程里面调用,目的是创建一个新的Looper,且一个线程只能创建一个Looper.public static void prepare() {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per ...

美溪区13368048926: 手机android系统 怎么看log -
寇虾盐酸: 使用cmd命令查看logcat 使用adb logcat命令可查看android系统和应用的log adb logcat //显示全部日志adb logcat > c:\test.log //将日志输出保存到文件test.log lo...

美溪区13368048926: 如何分析一个Android程序 -
寇虾盐酸: 1、新建一个Android项目,名字叫 CrackMe01,2、 接着编写MainActivity 里面的代码,先写一个checkSN ( String userName , String sn )方法,代码如下:[java] view plaincopyprivate boolean checkSN(String userName ,String sn) {// TODO ...

美溪区13368048926: 如何快速看懂一个Android项目 -
寇虾盐酸: 我个人做法:1. 安装App 使用各个功能2. 查看项目分包结构3. 查看AndroidManifest.xml(看有哪些Activity)4. 查看布局xml、Activity5. 看看其他的细分

美溪区13368048926: 很大的一个android项目怎样去读代码? -
寇虾盐酸: Android源码两个部分看得最多,一个是packages,就是各个系统应用的实现,另外就是framework,框架层的实现.具体看什么就看想了解什么. 工具eclipse也很好,build一下生成class path,各种转跳非常方便,不需要grep了. 1、使用工具Android Studio2、查看源码方法: 使用Android Studio查看Android Lollipop源码 // Android Performance3、查看部分:1).Framework/base 2).Package/apps 3).art 4).external

美溪区13368048926: android怎么才能看懂log日志 -
寇虾盐酸: 左边的Saved Filters是选择项目,右上角的点击verbose可以选择,如果选debug是调试,字体是蓝色;如果选是warn是警告,字体黄色;如果选error是错误,字体红色,一般就选这三个就行,如果不选默认verbose是打印所有log日志

美溪区13368048926: 深入理解ANDROID怎么样 -
寇虾盐酸: 现在市面很多android内核的书,但大部分都是从网上抄,要不就是翻译英文文档.本人粗读了四本,相较之下,《深》这本书质量还是很高的.大部分内容是作者自己做过实验的.不过下载android源码这部分确实现在已经不能用了,建议更新一下,或者作者自己试试. 现在好像卷2也要出了,还是可以考虑买本看.

美溪区13368048926: 怎么看 android 系统版本 比如:系统版本 android版本 基带版本~~之类 -
寇虾盐酸: 你的问题有点不明白阿.所谓版本,就是一个东西,做了功能的添加修改删除等之后,为了和之前东西区别,就做了号码的标记,就是版本号.一个系统开发,是有不同层的.有内核阿,应用层阿,画面等等.不同的区域,开发是相对独立的....

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网