Android系统学习2——Android.Utils.Log模块讨论

​ 打日志是一个很好的习惯,有的时候我们可以通过这里排查我们的程序的问题。在这里,我们可以从Android的日志机制入手讨论我们的Log模块。

android.util.Log 类的作用

Android 中最常用的日志工具是 android.util.Log,它提供了多个静态方法来打印日志:

  • Log.v()(Verbose)
  • Log.d()(Debug)
  • Log.i()(Info)
  • Log.w()(Warning)
  • Log.e()(Error)

Stack Overflow 的实战建议:

Log.e:用于捕获“真正”的错误,比如异常捕获块中。
Log.w:用于捕获“可疑”但不至于崩溃的情况。
Log.i:表示成功或信息性的状态,如连接成功。
Log.d:用于调试,打印变量、执行流程等。
Log.v:用于“疯狂”式的日志输出,记录非常详细的信息。这个信息可以用来最大程度的登记我们的信息

2. 底层机制如何运作?

  • android.util.Log 的方法最终调用一个 native 方法 println_native,这个 native 方法将日志发送到系统底层的 logd 服务。
  • 对于 C/C++ 层的日志,通过 liblog(NDK 中的日志库)实现,最终同样写入 logd,日志被分发到不同的环形缓存(circular buffers):main(主应用日志)、system(系统日志)、crash(崩溃日志)等 。

日志在发出后,会经过不同级别的过滤:

  1. 编译时过滤:ProGuard 等工具可以移除 Log.dLog.v 等日志。
  2. 系统属性过滤:若设置了 log.tag.<TAG> 属性,liblog 会根据其值决定是否发送该日志。
  3. 应用级过滤:通过 __android_log_set_minimum_priority,可设置最低日志等级,默认是 INFO
  4. 展示过滤adb logcat 或 Android Studio 可按 tag/级别过滤展示内容。

Logcat 与 Android Studio 的配合使用

Logcat 是什么?

Logcat 是 Android 提供的日志查看工具,包括:

  • 命令行工具:adb logcat 或直接在设备 shell 中执行 logcat
  • Android Studio 内置的 Logcat 窗口,可以实时查看设备或模拟器产生的日志

在 Android Studio 中,Logcat 窗口默认显示每条日志的以下信息:日期、时间戳、进程 ID、线程 ID、Tag、包名、优先级、消息内容,不同优先级使用不同颜色显示,便于快速识别(例如 Error 通常是红色)

如何高效使用 Logcat?
  • 过滤功能:可根据 Log 等级(Verbose、Debug、Info、Warning、Error、Assert)过滤日志,只关注重要内容
  • 文本搜索:支持文本或正则表达式搜索日志内容
  • 自定义过滤器:Android Studio 会自动为 debuggable 应用生成过滤器,也可以自行创建过滤条件(tag、应用包名等)
  • 分区查看:在 Logcat 面板中,可以开启“Scroll to End”、暂停、清除日志等控制按钮来方便查看

原理分析

总体架构:从 Logliblog 再到 logd 与环形缓冲区

Android 的日志系统由系统进程 logd 维护的结构化环形缓冲区组成。各语言层(Java/Kotlin、C/C++)的日志最终都会进入这些缓冲区,然后由 IDE(Android Studio 的 Logcat 视图)或命令行工具(adb logcat)读取与过滤。缓冲区是循环覆盖的(不是无限增长,也不会跨重启持久化,除非设备厂商/工程构建开启了持久化日志服务)。

日志写入路径大致如下:

  • 应用层android.util.Log(Java/Kotlin)或 <android/log.h>(NDK)。
  • 系统库:所有语言最终会调用 __android_log_write(位于 liblog),默认通过 socket 将日志条目送至 logd。从 API 30 起,可以通过 __android_set_log_writer 替换默认写入函数(通常用于特殊场景或主机端单元测试)。
  • 缓冲区(主要)main(应用为主)、system(系统组件)、crash(崩溃相关)等。NDK 文档列出 MAIN / EVENTS / CRASH / KERNEL / DEFAULT 等 ID,并明确普通应用仅能写入/访问 MAIN

Android 将不同来源、不同优先级的消息统一汇聚到这些缓冲区,形成最终你在 Logcat 中看到的“混合”流。AOSP 文档也特别指出,Logcat 里混合了不同标准(如 android.util.Logsyslog 风格等)的日志


2)android.util.Log 的 API 与真实行为

Log 提供六个主流级别(VERBOSE/DEBUG/INFO/WARN/ERROR/ASSERT),对应静态方法 v/d/i/w/e/wtf,以及底层的 println() 重载。Logcat 过滤时常用到首字母:V/D/I/W/E/AS(silent)常用作过滤规格中的“全静音”。(级别与过滤法在命令行与 IDE 里一致,文后有速查。)

isLoggable() 与系统属性开关

Log.isLoggable(tag, level) 可在运行时读取系统属性 log.tag.<TAG>(或全局 log.tag)来判断某个 tag 在某级别是否应当输出,从而避免拼接大对象或格式化字符串的性能开销。例如:

private const val TAG = "BillingManager"fun query() {if (Log.isLoggable(TAG, Log.DEBUG)) {Log.d(TAG, "Querying items: ${expensiveToString(items)}")}
}

这一行为在 AOSP 源码 Log.java 里写得很清楚:它会查询系统属性来决定是否可记录。

实用例:临时开启某 tag 的 DEBUG
adb shell setprop log.tag.BillingManager DEBUG(需开发者设备/有权设置属性环境)→ 你的 isLoggable(..., DEBUG) 即会返回 true(直到设备重启/属性被还原)。

Tag 的长度限制(历史与现状)

AOSP 在 Log.java 的注释中提到:在 Android 7.0(Nougat)及更早版本中,tag 长度曾经被强制限制为 23 个字符。后续版本放宽了这一限制,但出于兼容性考虑,某些分组/过滤默认行为仍保留历史痕迹(避免与旧系统混用时出现“错误分组”)。如果你在维护非常老的设备或需要兼容老系统,这条历史尤为重要;新系统上则基本不用刻意把 tag 缩到 23 以内。

Log.wtf()(What a Terrible Failure)

wtf() 用于记录绝不应该发生的错误情况。AOSP 注释直言:可能导致进程退出(取决于系统配置),因此请仅在“逻辑上不可能出现”的致命条件下使用。IDE/命令行里它对应 ASSERT 级别。

其他便利用法
  • Log.getStackTraceString(Throwable):将异常堆栈转为字符串,避免你自己 StringWriter/PrintWriter 的样板代码。

Android Studio 的 Logcat(即“Logcat v2”)——更强大的 IDE 端查询与 UI

从新版 Android Studio 起,Logcat 采用流式视图与键值式查询语法,能非常方便地组合条件过滤,例如:

  • package:com.example.myapp level:W(仅看你应用的警告及以上)
  • tag:OkHttp|OkHttpClient level:D(多个 tag 的或关系)
  • pid:12345uid:10234、时间范围、正则等

Logcat 视图还支持分栏(Split)、**固定(Pin)**多个查询、历史自动补全与更灵活的布局/配色设置。进入 Settings > Tools > Logcat 可调整循环缓冲读入、默认过滤器、历史补全等;配色在 Editor > Color Scheme > Android Logcat


命令行 adb logcat 速查:从过滤规格到缓冲区与格式

命令行在 CI、远程联调或采集日志包时非常关键。官方文档要点如下:

常用命令与过滤规格(filterspec)

  • 基本:

    adb logcat                # 持续输出
    adb logcat -d             # dump 一次并退出
    adb logcat -c             # 清空缓冲区(慎用)
    
  • 过滤规格(经典语法): TAG:LEVEL *:S
    例如:adb logcat MyTag:D *:S(只看 MyTag 的 DEBUG 及以上,其它静默)。LEVEL 取 V/D/I/W/E/A

  • 按进程/用户过滤:

    adb logcat --pid=$(pidof com.example.myapp)
    adb logcat --uid=10234
    
  • 选择缓冲区: -b <buffer>
    常见:main(默认)、systemcrash、(设备/构建不同还可能有 eventsradio 等)。
    例:adb logcat -b crash *:S(只看崩溃缓冲区)。

  • 输出格式: -v <format>
    常用 threadtime(包含日期、时间、PID/TID、级别、tag、消息),也有 rawtimelong 等。

  • 缓冲区大小:

    • 查看:adb logcat -g
    • 设置:adb logcat -G 10M(需具备相应权限/构建允许)

NDK 侧说明:LOG_ID_MAIN应用唯一可用的日志缓冲区;其它如 EVENTS/CRASH/KERNEL 通常不对三方应用开放。


5)权限与可见性:为什么应用“看不到别人的日志”

  • 普通第三方应用不能随意读取系统/他应用的 Logcat。早年曾有 READ_LOGS 权限,但现在仅限系统/同签名应用使用;你的应用只能读取自己产生的日志
  • 开发时,通过 adb(USB 调试) 可以从主机上查看系统范围的日志(受设备安全策略与构建类型影响)。IDE 的 Logcat 也正是借助这一渠道做富交互过滤与展示。

6)性能与隐私安全:必须重视的硬性要求

  • 避免记录任何 PII/敏感信息(账号、令牌、位置、联系人、银行卡等),除非这对应用核心功能绝对必要;Android 安全最佳实践与合规指南明确提出此要求。
  • 发布版尽量减少/去除冗余日志:可以在发布构建里借助 Log.isLoggable()、编译器优化或混淆配置减少日志开销与暴露面(同时保留必要的错误/关键指标)。OWASP 移动安全测试指南同样建议在生产版避免输出敏感数据。
  • 性能注意:对大对象 toString()、字符串拼接、昂贵计算要先用 isLoggable() 判定再输出,避免在日志被过滤时仍然产生计算/分配成本。(见第 2 节示例。)

一些搜集到的问题:

  • 为何某些日志“重复被折叠/合并”:系统为抑制刷屏,logd/Logcat 会对大量重复行做“chatty” 合并(你会看到类似合并提示行)。这是日志守护进程层面的限流策略,用于提升可读性与性能。官方命令行文档在“日志系统概述”中描述了 logd 与缓冲区特性(合并提示本质上来自 logd 的输出策略)。
  • 崩溃日志在哪看
    • Java/Kotlin 崩溃栈会进入 Logcat,并可在 -b crash 缓冲区快速定位。
    • Native 崩溃还会产生 tombstone 文件,AOSP 有完整的排查文档,配合 Logcat 能更快锁定原因。
  • 缓冲区容量不够(日志被覆盖):用 adb logcat -g 看大小,必要时临时用 -G 调大(注意设备/构建权限)。IDE 侧也可以在 Settings > Tools > Logcat 调整读取策略与默认过滤器,提高“看到关键行”的概率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96947.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96947.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/96947.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 YAML 文件,如何优雅地删除 k8s 资源?

在 Kubernetes 中&#xff0c;删除资源是日常运维中不可避免的操作。如果你习惯了使用 kubectl create 和 kubectl apply 来创建和更新资源&#xff0c;那么你可能也会想知道如何用同样基于文件的方式来删除它们。 虽然你总是可以用 kubectl delete deployment <name> 这…

如何将游戏和软件移动到另一个驱动器或外部磁盘中

您的C盘存储空间是否不足&#xff0c;或者您不小心在错误的驱动器中安装了游戏或应用程序。那么使用这个简单的技巧&#xff0c;您可以轻松的将游戏或应用程序移动到另一个分区或磁盘中。1、找到准备移动的软件&#xff0c;选择路径并复制&#xff1a;2、打开记事本&#xff0c…

赋能汽车电子智造:全星QMS打造品质检验、稽核与客诉管理闭环​——全星质量管理软件系统

全星QMS&#xff1a;驱动汽车电子质量卓越与商业成功的核心引擎 在智能汽车时代&#xff0c;汽车电子的质量已成为产品安全、性能与品牌信誉的核心。面对复杂的供应链、严苛的IATF 16949/ISO 26262标准及降本增效的压力&#xff0c;您的企业需要一位数字化战略伙伴。全星质量管…

【数据结构C语言】顺序表

1. 线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串...线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线…

AI 学习路径-记录分享

目录推荐学习资源延申阅读推荐学习资源 3Blue1Brown的个人空间-3Blue1Brown个人主页-哔哩哔哩视频 这个简短的课程有助于了解AI的本质&#xff0c;迈入学习AI的第一步。 欢迎加入 &#x1f917; AI Agents 课程 - Hugging Face Agents Course AI Agent&#xff0c;当前火爆…

Windows Server 2019 上安装 Ubuntu 20.04 的几种方式

docker desktop不支持Windows server 2019&#xff0c;所以Windows Server 2019 上安装 Ubuntu 20.04 变成一种可行的途径。记录一下其中可用的几种方式&#xff1a;&#x1f5c2; 常见安装方式对比方式原理难度适用场景优点缺点Hyper‑V 虚拟机&#xff08;推荐&#xff09;利…

当Trae遇上高德MCP:一次国庆武汉之旅的AI技术实践

当Trae遇上高德MCP&#xff1a;一次国庆武汉之旅的AI技术实践 &#x1f31f; Hello&#xff0c;我是摘星&#xff01; &#x1f308; 在彩虹般绚烂的技术栈中&#xff0c;我是那个永不停歇的色彩收集者。 &#x1f98b; 每一个优化都是我培育的花朵&#xff0c;每一个特性都是我…

设计模式:抽象工厂模式

简介 抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种封装一组具有共同主题或相关依赖关系的独立工厂的方式,而无需指定它们的具体类。核心思想是创建一系列相关或相互依赖的对象家族(产品族),可以将客户端与具体产品的创建过程解耦,使得客…

知行——同为科技24周年庆典

在宜人的金秋时节&#xff0c;北京同为科技有限公司于2025年8月23日&#xff0c;天津基地与江西同时隆重举办了以“知行”为主题的周年庆祝活动&#xff0c;回顾企业24年来的奋斗历程&#xff0c;凝聚“同为人”力量&#xff0c;展望更加光明的未来。当天&#xff0c;创始人周慧…

RK android14 定制ES8388音频编解码器双MIC双OUT(1)

文章目录 前言 一、适配内容概述 二、适配步骤 1. HAL层配置修改 1.1 添加声卡名称识别 (`audio_hw.c`) 1.2 注册声卡路由配置 (`config_list.h`) 1.3 定义路由配置表 (`es8388_config.h`) 2. 内核设备树修改 2.1 禁用默认声卡 2.2 配置ES8388声卡节点 2.3 配置I2C和Codec节点 …

Oracle跟踪及分析方法

1、SQL_TRACE 通过设置 SQL_TRACE 可以启用或禁用 SQL 跟踪工具&#xff0c;设置 SQL_TRACE 为 true 可以收集信息用于性能优化或问题诊断&#xff1b; 特别注意&#xff1a; 全局启用 SQL 跟踪可能会对性能产生严重影响。 可以使用 ALTER SESSION 跟踪特定会话。 Oracle 已…

第三阶段数据库-9:循环,编号,游标,分页

1_sql中的循环&#xff0c;编号&#xff08;1&#xff09;sql 中没有for循环&#xff0c;只有while循环&#xff0c;begin end 中间的就是while执行的语句&#xff0c;相当于{}declare i int; set i1; --begin end 中间的就是while执行的语句&#xff0c;相当于{} while(i<…

Redis高级篇:在Nginx、Redis、Tomcat(JVM)各环节添加缓存以实现多级缓存

摘要&#xff1a;多级缓存通过在 Nginx、Redis、Tomcat&#xff08;JVM&#xff09;各环节添加缓存&#xff0c;解决传统缓存中 Tomcat 瓶颈与 Redis 失效冲击数据库问题。利用 Caffeine 实现 JVM 缓存&#xff0c;OpenResty 结合 Lua 处理 Nginx 层逻辑&#xff0c;通过 Redis…

9 设计网络爬虫

前言 我们重点讨论网络爬虫的设计&#xff0c; 这也是一个有趣且经典的系统设计面试问题。 爬虫开发的复杂性取决于我们想要支持的爬虫规模。它可以是一个小的学校项目&#xff0c;只需要几小时就可以完成&#xff0c;也可以是一个需要专业开发团队持续优化的巨型项目。因此&…

面试:计算机网络

一、网络分层与URL流程 1. 模型掌握TCP/IP四层模型&#xff1a;层级功能 & 协议应用层提供应用接口&#xff08;HTTP、DNS、FTP&#xff09;传输层端到端传输&#xff08;TCP可靠、UDP快速&#xff09;网络层路由与寻址&#xff08;IP、ICMP&#xff09;网络接口层链路传输…

lanczos算法的核心——Ritz向量的计算(主要思想为反向映射)

在 Lanczos 算法中&#xff0c;“将得到的特征向量映射回原始空间&#xff08;即乘以V&#xff09;得到的近似特征向量” 这一步&#xff0c;通常是指在三对角矩阵&#xff08;T&#xff09;的特征向量求解完成后&#xff0c;将其转换回原始矩阵&#xff08;A&#xff09;的特征…

Verilog功能模块--SPI主机和从机(03)--SPI从机设计思路与代码解析

前言 上一篇文章介绍了Verilog功能模块——SPI主机&#xff0c;包括主机设计思路与使用方法。 本文则用纯Verilog设计了功能完整的4线SPI从机&#xff0c;与网上一些以高频率clk时钟模拟从机不同&#xff0c;本文中的SPI从机工作时钟来源于主机的sclk&#xff0c;符合SPI同步…

【Big Data】Hadoop YARN 大数据集群的 “资源管家”

Apache Hadoop YARN&#xff08;Yet Another Resource Negotiator&#xff09;是Hadoop生态系统中的核心资源管理框架&#xff0c;通过解耦资源管理和任务调度&#xff0c;提供了一个通用的分布式计算资源调度平台&#xff0c;使Hadoop从单一的MapReduce框架演进为支持多种计算…

【计组】总线与IO

总线同步定时方式采用公共时钟信号协调发送方和接收方的传送异步定时方式采用握手信号来实现定时控制不互锁对于主设备&#xff1a;请求&#xff0c;隔一段时间自动撤销请求对于从设备&#xff1a;回答&#xff0c;隔一段时间自动撤销回答半互锁对于主设备&#xff1a;请求&…

技术速递|Model Context Protocol (MCP) 支持已上线 JetBrains、Eclipse 和 Xcode

模型上下文协议&#xff08;MCP&#xff09;与 GitHub Copilot 的集成现已全面支持 JetBrains、Eclipse 和 Xcode&#xff01;MCP 使 GitHub Copilot 能够与外部工具和数据源集成&#xff0c;从而提升更深入的上下文感知能力和编码智能。 借助 JetBrains、Eclipse 和 Xcode 中…