Android art monitor_android.cc 源码分析

embedded/2025/2/24 22:59:51/

源码分析

#include "monitor.h"#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>#include <log/log.h>
#include <log/log_event_list.h>#include "art_method.h"
#include "jni/jni_env_ext.h"
#include "palette/palette.h"
#include "thread.h"// 定义了一个日志标签 EVENT_LOG_TAG_dvm_lock_sample,用于标识锁竞争事件的日志
#define EVENT_LOG_TAG_dvm_lock_sample 20003namespace art HIDDEN {// Thread* self:当前线程对象。
// uint32_t wait_ms:线程等待锁的时间(毫秒)。
// uint32_t sample_percent:采样百分比。
// ArtMethod* owner_method:锁持有者的方法。
// uint32_t owner_dex_pc:锁持有者的代码位置(Dex 文件中的程序计数器)。
void Monitor::LogContentionEvent(Thread* self,uint32_t wait_ms,uint32_t sample_percent,ArtMethod* owner_method,uint32_t owner_dex_pc) {// 创建了一个日志上下文对象 ctx,用于记录锁竞争事件的日志。android_log_event_list ctx(EVENT_LOG_TAG_dvm_lock_sample);const char* owner_filename;int32_t owner_line_number;// 使用 TranslateLocation 函数将方法和程序计数器(PC)转换为文件名和行号TranslateLocation(owner_method, owner_dex_pc, &owner_filename, &owner_line_number);// 从 /proc/self/cmdline 文件中读取当前进程的名称,并将其记录到日志中// Emit the process name, <= 33 bytes.char proc_name[33] = {};{int fd = open("/proc/self/cmdline", O_RDONLY  | O_CLOEXEC);read(fd, proc_name, sizeof(proc_name) - 1);close(fd);ctx << proc_name;}// Emit the sensitive thread ("main thread") status. We follow tradition that this corresponds// to a C++ bool's value, but be explicit.// 记录当前线程是否为“敏感线程”。在 Android 系统中,主线程(main thread)通常被认为是“敏感线程”,// 因为它负责处理 UI 事件和用户交互。如果主线程被阻塞(例如等待锁),可能会导致应用程序响应缓慢甚至出现 // ANR(Application Not Responding)错误。// 遵循了一个传统做法,即用 C++ 的布尔值(bool)来表示线程是否为敏感线程。// 在 C++ 中,true 对应于非零值(通常是 1),而 false 对应于 0// 尽管布尔值的表示是约定俗成的,但为了代码的可读性和明确性,这里通过定义常量来显式地表示布尔值constexpr uint32_t kIsSensitive = 1u;constexpr uint32_t kIsNotSensitive = 0u;ctx << (Thread::IsSensitiveThread() ? kIsSensitive : kIsNotSensitive);// Emit self thread name string.// 获取当前线程的名称std::string thread_name;self->GetThreadName(thread_name);ctx << thread_name;// Emit the wait time.// 记录当前线程等待锁的时间ctx << wait_ms;// 获取当前线程的代码位置(文件名、行号和方法名),并记录到日志中const char* filename = nullptr;int32_t line_number;std::string method_name;{uint32_t pc;ArtMethod* m = self->GetCurrentMethod(&pc);TranslateLocation(m, pc, &filename, &line_number);// Emit the source code file name.ctx << filename;// Emit the source code line number.ctx << line_number;// Emit the method name.method_name = ArtMethod::PrettyMethod(m);ctx << method_name;}// 记录锁持有者的代码位置(文件名、行号和方法名)。如果锁持有者的代码位置与当前线程相同,则使用 - 表示// 注意:持有者的文件名有可能为空// Emit the lock owner source code file name.if (owner_filename == nullptr) {owner_filename = "";} else if (strcmp(filename, owner_filename) == 0) {// Common case, so save on log space.owner_filename = "-";}ctx << owner_filename;// Emit the source code line number.ctx << owner_line_number;// Emit the owner method name.std::string owner_method_name = ArtMethod::PrettyMethod(owner_method);ctx << owner_method_name;// Emit the sample percentage.// 记录锁竞争事件的采样百分比ctx << sample_percent;// 记录日志类型为event日志ctx << LOG_ID_EVENTS;// Now report to other interested parties.// 将锁竞争事件的信息传递给其他组件PaletteReportLockContention(self->GetJniEnv(),wait_ms,filename,line_number,method_name.c_str(),owner_filename,owner_line_number,owner_method_name.c_str(),proc_name,thread_name.c_str());
}}  // namespace art

举例说明

02-10 14:05:43.759  1000  2649 16342 I dvm_lock_sample: [
system_server,
1,
binder:2649_1D,
9865,
AccessibilityWindowManager.java,
1456,
void com.android.server.accessibility.AccessibilityWindowManager.removeAccessibilityInteractionConnection(android.view.IWindow),
-,
1472,
void com.android.server.accessibility.AccessibilityWindowManager.removeAccessibilityInteractionConnection(android.view.IWindow),
2733]

dvm_lock_sample日志的各个信息为:

  • 进程:system_server
  • 线程:binder:2649_1D
  • 锁等待时间:9865ms
  • 当前线程的代码位置:
    • 文件:AccessibilityWindowManager.java
    • 行号:1456
    • 方法:void removeAccessibilityInteractionConnection(android.view.IWindow)
  • 锁持有者的代码位置:
  • 文件:AccessibilityWindowManager.java(与当前线程相同)
    • 行号:1472
    • 方法:void removeAccessibilityInteractionConnection(android.view.IWindow)
    • 采样百分比:2733

从这条日志可以看出:
当前线程和锁持有者处于同一个文件和方法中。
锁等待时间较长(9865ms),这可能表明存在性能问题,尤其是在主线程(敏感线程)中。


http://www.ppmy.cn/embedded/164909.html

相关文章

基于SSM的《计算机网络》题库管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘 要 《计算机网络》题库管理系统是一种新颖的考试管理模式&#xff0c;因为系统是用Java技术进行开发。系统分为三个用户进行登录并操作&#xff0c;分别是管理员、教师和学生。教师在系统后台新增试题和试卷&#xff0c;学生进行在线考试&#xff0c;还能对考生记录、错题…

【目标检测】【BiFPN】EfficientDet:Scalable and Efficient Object Detection

EfficientDet&#xff1a;可扩展且高效的目标检测 0.论文摘要 模型效率在计算机视觉中变得越来越重要。在本文中&#xff0c;我们系统地研究了用于目标检测的神经网络架构设计选择&#xff0c;并提出了几项关键优化以提高效率。首先&#xff0c;我们提出了一种加权双向特征金…

elf_loader:一个使用Rust编写的ELF加载器

本文介绍一个使用Rust实现的ELF加载器。 下面是elf_loader的仓库链接&#xff1a; github&#xff1a; https://github.com/weizhiao/elf_loaderhttps://github.com/weizhiao/elf_loader crates.io&#xff1a; https://crates.io/crates/elf_loaderhttps://crates.io/cra…

学习笔记02——《深入理解Java虚拟机(第三版)》第三章

一、核心脉络&#xff1a;垃圾回收与内存分配策略 核心命题&#xff1a;JVM如何高效管理内存的分配与回收&#xff1f; 三大核心机制&#xff1a; 对象存活判定&#xff08;引用追踪 vs 可达性分析&#xff09; 垃圾回收算法&#xff08;标记-清除/复制/标记-整理/分代&#…

mysql系列9—mysql的MVCC机制

背景 mysql提供了读未提交、读已提交、可重复读、串行化四种隔离级别&#xff0c;默认的隔离界别为可重复读。其中&#xff0c;不可重复度场景下&#xff0c;每次直接读取最新记录(即使事务未提交)&#xff1b;串行化对于所有的读写都加锁&#xff0c;因此&#xff0c;对二者不…

数据中心储能蓄电池状态监测管理系统 组成架构介绍

安科瑞刘鸿鹏 摘要 随着数据中心对供电可靠性要求的提高&#xff0c;蓄电池储能系统成为关键的后备电源。本文探讨了蓄电池监测系统在数据中心储能系统中的重要性&#xff0c;分析了ABAT系列蓄电池在线监测系统的功能、技术特点及其应用优势。通过蓄电池监测系统的实施&#…

LangChain大模型应用开发:多模态输入与自定义输出

介绍 大家好&#xff0c;博主又来给大家分享知识了。今天给大家分享的内容是使用LangChain进行大模型应用开发中的多模态输入与自定义输出。 LangChain中的多模态数据输入是指将多种不同形式的数据作为输入提供给基于语言模型的应用程序或系统&#xff0c;以丰富交互内容和提…

C++栈与队列:数据结构的“单行道”与“流水线

C栈与队列&#xff1a;数据结构的“单行道”与“流水线” 开篇小故事&#xff1a;火车站的两条轨道 想象一个火车站有两条特殊轨道&#xff1a; 轨道A&#xff08;栈&#xff09;&#xff1a;火车只能从同一端进出&#xff0c;最后进入的车厢必须先离开。轨道B&#xff08;队…