adb 有很多常用命令,今天主要就从用 logcat 抓取日志相关命令及抓取到的日志如何定位问题两方面进行展开讨论
前提
1、需安装Android sdk
2、了解一些adb 相关命令
待连接好手机,开启开发者模式后,就可以使用adb logcat命令抓取日志了
一、logcat 介绍
logcat是android中的一个命令行工具,可以用于得到程序的log信息
logcat 命令格式
adb logcat [<option>] … [<filter – spec>] …
logcat缓冲区
android log输出量巨大,特别是通信系统的log,因此,android把log输出到不同的缓冲区中,目前定义了四个log缓冲区:
- Radio:输出通信系统的log
- System:输出系统组件的log
- Event:输出event模块的log
- Main:所有java层的log,以及不属于上面3层的log
缓冲区主要给系统组件使用,一般的应用不需要关心,应用的log都输出到main缓冲区中
默认log输出(不指定缓冲区的情况下)是输出System和Main缓冲区的log
一般logcat默认手机最大有16KB的缓冲信息可以获取,所以有时候遇到崩溃时,及时抓取日志可能就可以抓取到崩溃信息,但如果正好缓冲区已满,新的就会覆盖掉旧的,这个时候只能再次触发崩溃,重新抓取日志
在开发者模式下,可以更改缓冲区大小
获取缓冲区命令
adb logcat -b <buffer> --默认值为main
例如:adb logcat –b events
二、logcat日志格式
不带任何参数的执行结果:
这样执行输出的日志很多,而且是实时监控的,看上去眼花缭乱,主要是因为没做筛选
从上图中可以看出,每列的日志信息分别为:日期、时间、PID、TID、日志级别、标签、日志内容
- PID:进程ID,可以看成app运行时,在系统中的唯一的一个标识
- TID:PID可以对应多个TID,主要是由于支持多线程。每个线程对应一个TID。
- 日志级别:Android Log类源码中,日志有6个级别 V(Verbose 明细,最低级别)、D(Debug 调试)、I(Info 信息)、W(Warn 警告)、E(Error 错误)、F(Fatal)
- 标签:tag号,开发时标记日志的一个属性。如,使用类名,表示是哪个类里输出的日志。
了解了每列日志的具体信息,就可以根据上述信息来筛选需要的日志
三、常用的筛选日志方法
- 根据PID筛选
一般这也是最常用的方式,由于手机中日志过多,可以只过滤某一个应用的日志,就可以使用这个方法
1)查找待测应用的进程ID:执行 adb shell dumpsys meminfo 应用包名 获取到 PID
2)根据PID筛选日志:执行 adb logcat | grep PID - 根据tag筛选
与PID筛选的方法类似,如果需要只过滤相关功能的日志,可以根据开发给出的tag来过滤
执行 adb logcat | grep tag - 根据日志级别筛选
有时候可能只需要关注一些重点问题的日志,所以可以根据级别来筛选
例如:筛选Warn级别以上的日志(包含Error)命令adb logcat *:W
四、logcat常用命令参数
-c | 清除缓冲区中的全部日志并退出(清除完后可以使用-g查看缓冲区) |
-d | 将缓冲区的log转存到屏幕中然后退出 |
-f <filename> | 将log输出到指定的文件中<文件名>.默认为标准输出(stdout) |
-g | 打印日志缓冲区的大小并退出 |
-n <count> | 设置日志的最大数目<count>,默认值是4,需要和-r选项一起使用 |
-r <kbytes> | 没<kbytes>时输出日志,默认值是16,需要和-f选项一起使用 |
-s | 设置过滤器 |
-v <format> | 设置输出格式的日志消息。默认是短暂的格式。支持的格式列表 |
例如: adb logcat -v time -f /sdcard/log.txt --把日志按照时间格式输出然后保存到手机的sdcard/log.txt里
adb logcat -v time >log.txt --把日志按照时间格式输出然后保存在电脑路径下的log.txt里
五、java常见的异常信息
一般抓取到日志后,崩溃信息可以通过过滤 Fatal 来查找
无响应的情况,可以过滤 ANR 来查找,一般出现无响应时,手机都会自动给本地保存一个traces文件,里面包含具体的日志信息
下面介绍下Java中比较常见的几种异常信息,针对出现不同的异常信息,也可以简单了解到有可能是哪些地方出现了这种问题
空指针:nullpointException
空指针就是空引用,java空指针异常就是引用本身为空,却调用了方法,这个时候就会出现空指针异常
一般出现的大多数原因都是未对读写操作进行容错等
数组越界:ArrayIndexoutof boundsException
当你使用不合法的索引访问数组时会报数组越界这种错误
一般是会出现在数组的赋值和取值时、列表中数据插入或删除时等
多次启动线程:illegalThreadstateException
单一线程重复启动,同一个线程未关闭时是不能重复启动的
有可能出现多个线程同时运行时,比如下载时又同时去请求等类似需要多线程同时操作的功能点
数字格式化问题 :java.lang.NumberFormatException
数字格式化问题,比如想把string 类型转换成数字类型
有可能会出现在读取接口返回时,格式转换错误或是输入内容时格式错误等
内存溢出:java.lang.OutOfMemoryError
主要原因是JVM内存过小、程序不严密,产生了过多的垃圾
一般可能会出现在内存中保存的数据量过大,一下加载过多的数据导致的