当前位置: 首页 > article >正文

Android 自己的智能指针

在 Android 系统中,强指针模板类(sp<T> 是一种基于引用计数的智能指针实现,专门用于管理对象的生命周期。它被广泛用于 Android Framework 的底层(Native 层/C++ 代码),尤其是与 Binder 通信相关的模块。

1. sp<T> 的定义与作用

  • 模板类sp<T> 是一个模板类(定义在 <utils/StrongPointer.h> 中),通过泛型支持任意类型的对象。
  • 强引用语义:通过引用计数(Reference Counting)跟踪对象的使用情况,确保对象在不再被任何指针引用时自动释放内存。
  • 设计目标:解决 Android 系统中 Native 层对象生命周期管理的复杂性,避免内存泄漏和野指针问题。

2. 强指针服务对象

引用计数机制
  • 每个被 sp<T> 管理的对象必须继承自 RefBase(定义在 <utils/RefBase.h>)。
  • RefBase 提供了两个引用计数器:
    • 强引用计数(Strong Count):由 sp<T> 管理,归零时对象被销毁。
    • 弱引用计数(Weak Count):由 wp<T>(弱指针)管理,归零时对象的控制块被释放(但对象内存可能已被强引用释放)。
sp<T> 的实现原理
  1. 构造 sp<T>
    sp<T> 指向一个对象时,会调用 RefBase::incStrong() 增加强引用计数。

    template<typename T>
    sp<T>::sp(T* other) : m_ptr(other) {if (other) other->incStrong(this);
    }
    
  2. 析构 sp<T>
    sp<T> 超出作用域或被重置时,调用 RefBase::decStrong() 减少强引用计数。若计数归零,销毁对象。

    template<typename T>
    sp<T>::~sp() {if (m_ptr) m_ptr->decStrong(this);
    }
    
  3. 赋值与拷贝
    拷贝或赋值操作会调整引用计数,确保新旧指针的正确管理:

    sp<ProcessState> p1 = new ProcessState(); // 强引用计数=1
    sp<ProcessState> p2 = p1;                 // 强引用计数=2
    

3. sp<T>RefBase 的关系

  • 对象必须继承 RefBase
    只有继承自 RefBase 的类才能被 sp<T> 管理。例如:

    class ProcessState : public virtual RefBase {// ...
    };
    
  • RefBase 的关键方法

    • incStrong():增加强引用计数。
    • decStrong():减少强引用计数,可能触发对象销毁。
    • onFirstRef():当强引用计数从 0 变为 1 时调用(首次被引用)。
    • onLastStrongRef():当强引用计数归零时调用(即将销毁)。

4. 使用场景示例

示例 1:Binder 代理对象的生命周期管理

在 Binder 通信中,客户端通过 sp<IBinder> 持有服务端的代理对象:

// 获取 ServiceManager 的代理
sp<IServiceManager> sm = defaultServiceManager();// 获取 BatteryService 的 Binder 代理对象
sp<IBinder> binder = sm->getService(String16("battery"));// 将 IBinder 转换为具体的服务接口
sp<IBatteryService> batteryService = interface_cast<IBatteryService>(binder);
  • sp<T> 确保代理对象在不再被使用时自动释放。
示例 2:单例模式的资源管理

ProcessState 单例中,使用 sp<T> 确保全局唯一实例的正确释放:

sp<ProcessState> ProcessState::self() {static sp<ProcessState> gProcess(new ProcessState);return gProcess;
}

5. sp<T> vs C++ 标准智能指针

特性sp<T> (Android)std::shared_ptr<T> (C++11)
依赖对象基类必须继承 RefBase无要求(通过 std::enable_shared_from_this 可选)
性能优化为嵌入式系统优化,轻量级通用实现,可能略重
线程安全引用计数操作是原子的(线程安全)默认线程安全(依赖实现)
弱指针支持通过 wp<T> 实现通过 std::weak_ptr<T> 实现
内存开销每个对象附带 RefBase 的控制块每个 shared_ptr 有单独的控制块

6. 注意事项

  1. 循环引用
    sp<T> 无法自动处理循环引用(如对象 A 持有 sp<B>,对象 B 持有 sp<A>),需结合 wp<T>(弱指针)打破循环。

  2. 继承 RefBase
    若类未继承 RefBase,使用 sp<T> 会导致编译错误。

  3. 跨模块传递
    确保对象的所有权通过 sp<T> 明确传递,避免裸指针(T*)脱离智能指针管理。

  4. 线程安全
    虽然 sp<T> 的引用计数操作是原子的,但对象本身的线程安全性需开发者自行保证。

相关文章:

Android 自己的智能指针

在 Android 系统中&#xff0c;强指针模板类&#xff08;sp<T>&#xff09; 是一种基于引用计数的智能指针实现&#xff0c;专门用于管理对象的生命周期。它被广泛用于 Android Framework 的底层&#xff08;Native 层/C 代码&#xff09;&#xff0c;尤其是与 Binder 通…...

如何在React中集成 PDF.js?构建支持打印下载的PDF阅读器详解

本文深入解析基于 React 和 PDF.js 构建 PDF 查看器的实现方案&#xff0c;该组件支持 PDF 渲染、图片打印和下载功能&#xff0c;并包含完整的加载状态与错误处理机制。 完整代码在最后 一个PDF 文件&#xff1a; https://mozilla.github.io/pdf.js/web/compressed.tracemo…...

【完美解决】VSCode连接HPC节点,已配置密钥却还是提示需要输入密码

目录 问题描述软件版本原因分析错误逻辑链 解决方案总结 问题描述 本人在使用 ​​VSCode Remote-SSH 插件​​连接超算集群节点时&#xff0c;遇到以下问题&#xff1a;已正确配置 SSH 密钥&#xff0c;且 VSCode 能识别密钥文件&#xff08;如图1&#xff09;&#xff0c;但在…...

智能DNS解析:解决高防IP地区访问异常的实战指南

摘要&#xff1a;针对高防IP在部分地区无法访问的问题&#xff0c;本文设计基于智能DNS的流量调度方案&#xff0c;提供GeoDNS配置与故障切换代码示例。 一、问题背景 运营商误拦截或线路波动可能导致高防IP在福建、江苏等地访问异常。传统切换方案成本高&#xff0c;智能DNS可…...

【JSON2WEB】16 login.html 登录密码加密传输

【JSON2WEB】系列目录 【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSO…...

ruby超高级语法

以下是 Ruby 中一些 极度硬核 的语法和底层特性&#xff0c;涉及元编程的深渊、虚拟机原理、语法黑魔法等&#xff0c;适用于追求极限的 Ruby 开发者&#xff1a; 高级语法一 一、语法核弹级操作 1. 动态修改继承链 class A; def foo; "A"; end end class B; def …...

第十二天 - Flask/Django基础 - REST API开发 - 练习:运维管理后台API

从零开始用Flask/Django构建运维管理后台API&#xff08;实战指南&#xff09; 前言&#xff1a;为什么选择Python Web框架&#xff1f; 在运维自动化领域&#xff0c;构建管理后台是每个运维工程师的必修课。本文将通过Flask和Django两个主流框架&#xff0c;手把手教你构建…...

Docker 容器内运行程序的性能开销

在 Docker 容器内运行程序通常会有一定的性能开销&#xff0c;但具体损失多少取决于多个因素。以下是详细分析&#xff1a; 1. CPU 性能 理论开销&#xff1a;容器直接共享宿主机的内核&#xff0c;CPU 调度由宿主机管理&#xff0c;因此 CPU 运算性能几乎与原生环境一致&…...

从递归入手一维动态规划

从递归入手一维动态规划 1. 509. 斐波那契数 1.1 思路 递归 F(i) F(i-1) F(i-2) 每个点都往下展开两个分支&#xff0c;时间复杂度为 O(2n) 。 在上图中我们可以看到 F(6) F(5) F(4)。 计算 F(6) 的时候已经展开计算过 F(5)了。而在计算 F(7)的时候&#xff0c;还需要…...

【2025年认证杯数学中国数学建模网络挑战赛】A题解题思路与模型代码

【2025年认证杯数学建模挑战赛】A题 该题为典型的空间几何建模轨道动力学建模预测问题。 ⚙ 问题一&#xff1a;利用多个天文台的同步观测&#xff0c;确定小行星与地球的相对距离 问题分析 已知若干地面天文台的观测数据&#xff1a;方位角 (Azimuth) 和 高度角 (Altitude)&…...

蓝桥杯备赛 Day16 单调数据结构

单调栈和单调队列能够动态的维护&#xff0c;还需用1-2两个数组在循环时从单调栈和单调队列中记录答案 单调栈 要点 1.时刻保持内部元素具有单调性质的栈(先进后出),核心是:入栈时逐个删除所有"更差的点",一般可分为单调递减栈、单调递增栈、单调不减栈、单调不增…...

轻量级爬虫框架Feapder入门:快速搭建企业级数据管道

一、目标与前置知识 1. 目标概述 本教程的主要目标是&#xff1a; 介绍轻量级爬虫框架 Feapder 的基本使用方式。快速搭建一个采集豆瓣电影数据的爬虫&#xff0c;通过电影名称查找对应的电影详情页并提取相关信息&#xff08;电影名称、导演、演员、剧情简介、评分&#xf…...

golang gmp模型分析

思维导图&#xff1a; 1. 发展过程 思维导图&#xff1a; 在单机时代是没有多线程、多进程、协程这些概念的。早期的操作系统都是顺序执行 单进程的缺点有&#xff1a; 单一执行流程、计算机只能一个任务一个任务进行处理进程阻塞所带来的CPU时间的浪费 处于对CPU资源的利用&…...

深入理解Java Optional:告别NullPointerException的优雅方式

大家好&#xff01;今天我们来聊聊Java 8引入的一个超实用类 - Optional。不是那个让你重启电脑的CtrlAltDel哦&#xff01;&#x1f604; 这是一个能让我们优雅处理null值的工具类&#xff0c;彻底告别烦人的NullPointerException&#xff01; 一、为什么需要Optional&#x…...

【算法竞赛】树上最长公共路径前缀(蓝桥杯2024真题·团建·超详细解析)

目录 一、题目 二、思路 1. 问题转化&#xff1a;同步DFS走树 2. 优化&#xff1a;同步DFS匹配 3. 状态设计&#xff1a;dfs参数含义 4. 匹配过程&#xff1a;用 map 建立权值索引 5. 终止条件&#xff1a;无法匹配则更新答案 6. 总结 三、完整代码 四、知识点总…...

【windows10】基于SSH反向隧道公网ip端口实现远程桌面

【windows10】基于SSH反向隧道公网ip端口实现远程桌面 1.背景2.SSH反向隧道3.远程连接电脑 1.背景 ‌Windows 10远程桌面协议的简称是RDP&#xff08;Remote Desktop Protocol&#xff09;‌。 RDP是一种网络协议&#xff0c;允许用户远程访问和操作另一台计算机。 远程桌面功…...

Python----概率论与统计(贝叶斯,朴素贝叶斯 )

一、贝叶斯 1.1、贝叶斯定理 贝叶斯定理&#xff08;Bayes Theorem&#xff09;也称贝叶斯公式&#xff0c;是关于随机事件的条件概率的定理 贝叶斯的的作用&#xff1a;根据已知的概率来更新事件的概率。 1.2、定理内容 提示&#xff1a; 贝叶斯定理是“由果溯因”的推断&…...

NO.88十六届蓝桥杯备战|动态规划-多重背包|摆花(C++)

多重背包 多重背包问题有两种解法&#xff1a; 按照背包问题的常规分析⽅式&#xff0c;仿照完全背包&#xff0c;第三维枚举使⽤的个数&#xff1b;利⽤⼆进制可以表⽰⼀定范围内整数的性质&#xff0c;转化成01 背包问题。 ⼩建议&#xff1a;并不是所有的多重背包问题都能…...

vue项目打包里面pubilc里的 tinymce里的js文件问题

以下是解决 Vue 项目打包后 public/tinymce 中 JS 文件路径问题的完整方案&#xff1a; 问题原因 当使用 public 目录存放静态资源时&#xff0c;Vue CLI 默认会将 public 下的文件 直接复制到打包目录的根路径&#xff0c;但以下操作可能导致路径错误&#xff1a; 开发环境使…...

Python星球日记 - 第18天:小游戏开发(猜数字游戏)

🌟引言: 上一篇:Python星球日记 - 第17天:数据可视化 名人说:路漫漫其修远兮,吾将上下而求索。(屈原《离骚》) 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、游戏概述与原理1. 游戏基本规则2. 编程知识点3.猜数字游戏流程图二、游戏逻辑设计…...

爬虫抓包工具和PyExeJs模块

我们在处理一些网站的时候, 会遇到一些屏蔽F12, 以及只要按出浏览器的开发者工具就会关闭甚至死机的现象. 在遇到这类网站的时候. 我们可以使用抓包工具把页面上屏蔽开发者工具的代码给干掉. Fiddler和Charles 这两款工具是非常优秀的抓包工具. 他们可以监听到我们计算机上所…...

无人机击落技术难点与要点分析!

一、技术难点 1. 目标探测与识别 小型化和低空飞行&#xff1a;现代无人机体积小、飞行高度低&#xff08;尤其在城市或复杂地形中&#xff09;&#xff0c;雷达和光学传感器难以有效探测。 隐身技术&#xff1a;部分高端无人机采用吸波材料或低可探测设计&#xff0c;进…...

2025年Java无服务器架构实战:AWS Lambda与Spring Cloud Function深度整合

摘要 &#x1f4dd; 本文深入探讨如何在2025年Java生态中实现AWS Lambda与Spring Cloud Function的无缝整合。我们将从基础概念讲起&#xff0c;逐步深入到实际部署、性能优化和最佳实践&#xff0c;通过详实的代码示例展示如何构建高效、可扩展的无服务器Java应用。 目录 &a…...

LeetCode 题目 「二叉树的右视图」 中,如何从「中间存储」到「一步到位」实现代码的优化?

背景简介 在 LeetCode 的经典题目 「二叉树的右视图」 中&#xff0c;我们需要返回从右侧看一棵二叉树时所能看到的节点集合。每一层我们只能看到最右边的那个节点。 最初&#xff0c;我采用了一个常规思路&#xff1a;层序遍历 每层单独保存节点值 最后提取每层最后一个节…...

8.第二阶段x64游戏实战-string类

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;7.第二阶段x64游戏实战-分析人物属性 string类是字符串类&#xff0c;在计算机中…...

Go语言sync.Mutex包源码解读

互斥锁sync.Mutex是在并发程序中对共享资源进行访问控制的主要手段&#xff0c;对此Go语言提供了非常简单易用的机制。sync.Mutex为结构体类型&#xff0c;对外暴露Lock()、Unlock()、TryLock()三种方法&#xff0c;分别用于阻塞加锁、解锁、非阻塞加锁操作&#xff08;加锁失败…...

C++实现文件断点续传:原理剖析与实战指南

文件传输示意图 一、断点续传的核心价值 1.1 大文件传输的痛点分析 网络闪断导致重复传输&#xff1a;平均重试3-5次。 传输进度不可回溯&#xff1a;用户无法查看历史进度。 带宽利用率低下&#xff1a;每次中断需从头开始。 1.2 断点续传技术优势 指标传统传输断点续传…...

MySQL中FIND_IN_SET函数与INSTR函数用法解析

一、功能定义与语法 1、FIND_IN_SET函数 语法&#xff1a;FIND_IN_SET(str, strlist) 功能&#xff1a;在逗号分隔的字符串列表&#xff08;strlist&#xff09;中查找精确匹配的子字符串&#xff08;str&#xff09;&#xff0c;并返回其位置&#xff08;从1开始&#xff09…...

Python贝叶斯回归、强化学习分析医疗健康数据拟合截断删失数据与参数估计3实例

全文链接&#xff1a;https://tecdat.cn/?p41391 在当今数据驱动的时代&#xff0c;数据科学家面临着处理各种复杂数据和构建有效模型的挑战。本专题合集聚焦于有序分类变量处理、截断与删失数据回归分析以及强化学习模型拟合等多个重要且具有挑战性的数据分析场景&#xff0c…...

Git 协同开发的常用操作

1. 单仓库&#xff08;多分支开发&#xff09; 从远程拉取代码 git clone https://gitee.com/...查看当前分支 git branch -- *master创建并切换到你的开发分支&#xff08;my-dev&#xff09; git checkout -b my-dev查看当前分支 git branch -- marster -- *my-dev提交代…...