Android日志[进阶篇]一-使用 Logcat 写入和查看日志
Android日志[进阶篇]二-分析堆栈轨迹(调试和外部堆栈)
Android日志[进阶篇]三-Logcat命令行工具
Android日志[进阶篇]四-获取错误报告
Android日志[进阶篇]五-阅读错误报告
Android Studio 中的 Logcat 窗口会显示系统消息,例如在进行垃圾回收时显示的消息,以及使用 Log
类添加到应用的消息。此窗口可以实时显示消息,也可以保留历史记录,因此可以查看较早的消息。
要仅显示感兴趣的信息,可以创建过滤器、修改消息中显示的信息量、设置优先级、仅显示通过应用代码生成的消息以及搜索日志。默认情况下,logcat 仅显示与最近运行的应用相关的日志输出。
如果应用抛出异常,logcat 会显示一条消息,后跟相关联的堆栈轨迹,其中包含指向相应代码行的链接。
从 Android Studio 2.2 开始,Run 窗口还会显示当前正在运行的应用的日志消息。请注意,可以配置 logcat 输出显示,但无法配置 Run 窗口。
如需显示应用的日志消息,请执行以下操作:
Logcat 窗口会显示所选应用(从窗口顶部的下拉列表中选择)的日志消息,如图 1 所示。
图 1. Logcat 窗口
默认情况下,Logcat 仅显示在设备上运行的应用的日志消息。要更改此默认设置,请参阅如何过滤 logcat 消息。
Logcat 工具栏中提供的按钮(如图1标号):
通过 Log
类,可以创建(输出)日志消息,这些消息会显示在 logcat 中。一般来说,使用以下日志方法,这些方法按照优先级从高到低(或者从最简略到最详细)的顺序列示:
Log.e(String, String)
(错误)Log.w(String, String)
(警告)Log.i(String, String)
(信息)Log.d(String, String)
(调试)Log.v(String, String)
(详细)有关更完整的选项列表,请参阅 Log
类说明。
除开发期间外,其他任何时候都绝不应将详细日志编译到您的应用中。虽然会编译调试日志,但会在运行时将其去掉,而错误、警告和信息日志会始终保留。
对于每种日志方法,第一个参数都应是唯一标记,第二个参数都应是消息。系统日志消息的标记是一个简短的字符串,指示消息所源自的系统组件(例如 ActivityManager
)。标记可以是有用的任何字符串,例如当前类的名称。
一种比较好的做法是,在要用于第一个参数的类中声明 TAG
常量。例如,可以按如下方式创建一条信息日志消息:
private static final String TAG = "MyActivity";
...
Log.i(TAG, "MyClass.getView() — get item number " + position);
注意:长度超过 23 个字符的标记名称在 logcat 输出中会被截断。
每个 Android 日志消息都有一个与之相关联的标记和优先级。系统日志消息的标记是一个简短的字符串,指示消息所源自的系统组件(例如 ActivityManager
)。用户定义的标记可以是任何字符串,例如当前类的名称(建议的标记)。可以在 Log
方法调用中定义它,例如:
Log.d(tag, message)
优先级低到高:
日志消息的格式为:
date time PID-TID/package priority/tag: message
例如,下面的日志消息的优先级为 V
,标记为 Eagle
:
12-10 13:02:50.071 1901-4229/com.eagle.app V/Eagle: Handling delegate intent.
PID 代表进程标识符,TID 则为线程标识符;如果仅有一个线程,两者可以相同。
可以通过设置日志级别来控制 logcat 中显示的消息数量。可以显示所有消息,也可以仅显示指示最严重情况的消息。
请注意,无论日志级别设置如何,logcat 都会继续收集所有消息。此设置仅决定 logcat 显示什么。
在“Log level”菜单中,选择以下值之一:
要搜索 logcat 中当前显示的消息,请执行以下操作:
Logcat 输出会相应地显示更改。
将日志输出减少至可管理水平的一种方法是,使用过滤器施加限制。
注意:过滤器会应用于 logcat 的全部历史记录,而不仅仅是 logcat 中当前显示的消息。确保适当地设置其他显示选项,以便能够看到想要检查的过滤器输出。
要定义并应用过滤器,请执行以下操作:
要移除过滤器,请在左侧窗格中将其选中,然后点击 -。
如果没有看到想要检查的日志消息,请尝试选择 No filters再clean一下日志, 并搜索特定日志消息。
有时,发生垃圾回收事件时,相应消息会输出到 Logcat 中。
如需详细了解应用的内存,请使用内存性能分析器。
在 Dalvik(而不是 ART)中,每个 GC 都会将以下信息输出到 logcat 中:
D/dalvikvm(PID): GC_Reason Amount_freed, Heap_stats,
External_memory_stats, Pause_time
示例:
D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K,
external 4703K/5261K, paused 2ms+2ms
GC_CONCURRENT
GC_FOR_MALLOC
GC_HPROF_DUMP_HEAP
GC_EXPLICIT
gc()
时(开发者应避免调用它,而应信任 GC 会根据需要运行)。
GC_EXTERNAL_ALLOC
在此类日志消息积聚时,请注意堆统计数据(上面示例中的 3571K/9991K
值)的增大情况。如果此值继续增大,可能会出现内存泄露。
与 Dalvik 不同,ART 不会为未明确请求的 GC 记录消息。只有在系统认为 GC 速度较慢时才会输出 GC 消息。更确切地说,仅在 GC 暂停时间超过 5 毫秒或 GC 持续时间超过 100 毫秒时。如果应用未处于可察觉到暂停的状态(例如应用在后台运行时,这种情况下,用户无法察觉 GC 暂停),则其所有 GC 都不会被视为速度较慢。系统一直会记录显式 GC。
ART 会在其垃圾回收日志消息中包含以下信息:
I/art: GC_Reason GC_Name Objects_freed(Size_freed) AllocSpace
Objects,Large_objects_freed(Large_object_size_freed) Heap_stats LOS objects, Pause_time(s)
示例:
I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace
objects,21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms
Concurrent
Alloc
Explicit
gc()
或 gc()
。与 Dalvik 一样,在 ART 中,最佳做法是信任 GC 并避免请求显式 GC(如果可能)。不建议请求显式 GC,因为它们会阻止分配线程并不必要地浪费 CPU 周期。此外,如果显式 GC 导致其他线程被抢占,则也可能会导致卡顿(应用出现卡顿、抖动或暂停)。
NativeAlloc
CollectorTransition
回收器转换仅在以下情况下出现:在 Android 8.0 之前的低内存设备上,应用将进程状态从可察觉到暂停的状态(例如应用在前台运行时,这种情况下,用户可以察觉 GC 暂停)更改为察觉不到暂停的状态(反之亦然)。
HomogeneousSpaceCompact
DisableMovingGc
HeapTrim
Concurrent mark sweep (CMS)
Concurrent partial mark sweep
Concurrent sticky mark sweep
Marksweep + semispace
如果在 logcat 中看到大量 GC,请注意堆统计数据(上面示例中的 25MB/38MB
值)的增大情况。如果此值继续增大,且始终没有变小的趋势,可能会出现内存泄漏。或者,如果看到原因为“Alloc”的 GC,则您已快要达到堆容量上限,并且很快会出现 OOM 异常。