安卓智能指针sp、wp、RefBase浅析

目录

  • 前言
  • 一、RefBase
    • 1.1 引用计数机制
    • 1.2 设计目的
    • 1.3 主要方法
    • 1.4 如何使用
    • 1.5 小结
  • 二、sp和wp
    • 2.1 引用计数机制
    • 2.2 设计目的
    • 2.3 主要方法
      • 2.3.1 sp
      • 2.3.2 wp
    • 2.4 如何使用
    • 2.5 小结
  • 四、参考链接


前言

安卓底层binder中,为什么 IInterface要继承自RefBase ?常常看到的sp又是什么东西?想要搞懂安卓底层binder,又或是安卓NDK开发,你必须了解这些内容。

一、RefBase

RefBase 是 Android 系统中用于实现引用计数的基类,主要用于管理对象的生存周期。其设计是为了确保在多线程和多组件的环境中正确处理对象的引用计数,从而提高内存管理的安全性和效率。

1.1 引用计数机制

当一个对象被创建时,它的引用计数初始为 1。每当一个新的引用指向该对象时,引用计数加一;每当引用失效时,引用计数减一。当引用计数减到 0 时,对象的析构函数会被调用,内存将被释放。这样可以有效避免内存泄漏并确保在不需要时释放资源。

1.2 设计目的

在多线程环境中,使用引用计数可以使得对象的管理更加安全。当多个线程或组件引用同一个对象时,引用计数机制可以确保对象在引用未被完全释放之前不被销毁,避免了潜在的使用已释放对象的危害。

1.3 主要方法

RefBase 提供了一些基础方法来支持引用计数,例如:

  • incStrong() 和 decStrong():

这两个方法分别用于增加和减少对象的强引用计数。强引用保证了对象在有强引用存在时不会被销毁。

  • incWeak() 和 decWeak():

这些方法用于弱引用计数管理。弱引用允许对象在没有强引用时被销毁,因此不会阻止对象的析构。

  • getStrongCount() 和 getWeakCount():

返回当前的强引用和弱引用计数。

1.4 如何使用

在 Android 中,通常会通过 sp< T>wp< T> 类来使用 RefBase 的引用计数功能。
sp< T> 是一个智能指针,表示强引用,持有对象的强引用;
wp< T> 表示弱引用,持有对象的弱引用。

示例代码:

#include <utils/RefBase.h>class MyObject : public RefBase {  
public:  MyObject() { }  ~MyObject() { }  void doSomething() {  // 业务逻辑  }  
};  
int main() {  sp<MyObject> obj = new MyObject(); // 引用计数为 1  {  sp<MyObject> obj2 = obj; // 引用计数增加到 2  obj2->doSomething(); // 可以通过 obj2 调用方法  } // obj2 生命周期结束,引用计数减少到 1  // 继续使用 obj,不会被提前销毁  obj->doSomething();  // 当 obj 超出作用域后,引用计数减少到 0,对象会被销毁  return 0;  
}

1.5 小结

RefBase 是 Android 中用于引用计数的基础类。
提供了强引用和弱引用的管理机制,确保在多线程环境中安全地管理对象的生命周期。
使用 sp 和 wp 管理对象时,可以方便地实现内存安全和避免内存泄漏的风险。


二、sp和wp

强指针sp(Strong Pointer)和弱指针wp(Weak Pointer)

2.1 引用计数机制

sp 是一个智能指针,它使用引用计数机制来管理资源。当一个 sp 指针被复制时,它会增加对象的引用计数;当 sp 指针被销毁时,它会减少引用计数。

wp同理,只不过是区分为强引用计数和弱引用计数。

当引用计数变为零时(即没有任何 sp 指针指向该对象),对象会自动被销毁,释放所占的内存。

2.2 设计目的

  • 内存管理:通过引用计数机制,sp 和 wp 旨在简化对象的内存管理,避免内存泄露和不必要的内存占用。
  • 防止循环引用:使用 sp 和 wp,可以避免由于相互引用导致的循环引用,从而使对象无法释放。

2.3 主要方法

2.3.1 sp

在这里插入图片描述

  • 提供多种形式的构造方式
  • 定义多种形式的赋值运算操作
  • 重载操作运算符*,可以获取实际对象
  • 重载操作运算符->,可以获取指向实际对象的指针
  • 可通过get函数,获取实际对象的指针
  • force_set函数可以指定sp引用的实际对象,该函数设计有点缺点,若sp当前已经引用其他的对象,则可能造成其他对象无法释放。

2.3.2 wp

在这里插入图片描述

  • 提供多种形式的构造方式
  • 定义多种形式的赋值运算操作
  • 可通过unsafe_get函数,获取实际对象的指针,但是可能获取到的是空的或是野指针
  • 可以通过promote函数将弱引用变为强引用,这个是一个比较重要的函数。

2.4 如何使用

一个简单的小demo

#include <utils/RefBase.h>  
#include <iostream>  class MyClass : public android::RefBase {  
public:  MyClass(int value) : mValue(value) {  std::cout << "MyClass created with value: " << mValue << std::endl;  }  ~MyClass() {  std::cout << "MyClass destroyed with value: " << mValue << std::endl;  }  void displayValue() {  std::cout << "Value: " << mValue << std::endl;  }  private:  int mValue;  
};  void demonstrateSpAndWp() {  // 创建一个 sp 指向 MyClass 的实例  android::sp<MyClass> strongPtr = new MyClass(42);  strongPtr->displayValue(); // 使用 sp 指针调用方法  // 创建一个 wp 指向 sp 指针的对象  android::wp<MyClass> weakPtr = strongPtr;  // 尝试通过 wp 转换为 sp  if (android::sp<MyClass> tempPtr = weakPtr.promote()) {  tempPtr->displayValue(); // 使用转换后的 sp 指针调用方法  } else {  std::cout << "The object is already destroyed!" << std::endl;  }  // 删除 strongPtr,强引用计数减一  strongPtr = nullptr; // 这会导致 MyClass 对象被销毁  std::cout << "strongPtr set to nullptr." << std::endl;  // 再次检查 wp 指针  if (android::sp<MyClass> tempPtr = weakPtr.promote()) {  tempPtr->displayValue(); // 尝试访问已经被销毁的对象  } else {  std::cout << "The object is already destroyed!" << std::endl;  }  
}  int main() {  demonstrateSpAndWp();  return 0;  
}

创建一个 sp 指针 strongPtr,指向 MyClass 的实例。调用对象的方法来展示功能。
创建一个 wp 指针 weakPtr,指向 strongPtr。此时对象的引用计数依然有效。
使用 promote() 方法将 wp 转换为一个 sp 指针,以检查对象是否仍然有效并使用它。
将 strongPtr 置为空以释放对象,这将导致 MyClass 的析构函数被调用。
再次检查 weakPtr 指向的对象,证明对象已经被销毁,此时 promote() 将返回空指针,输出相关信息。

2.5 小结

  • sp 和 wp 是 Android 提供的智能指针类,使用引用计数机制来实现内存管理。
  • sp 主要用于对对象的强引用,自动管理对象的生命周期;
  • wp 用于对对象的弱引用,允许检测被引用对象的有效性,同时不会影响其生命周期。
  • 正确使用 sp 和 wp 可以有效地减少内存泄漏、提高内存管理的安全性,并防止循环引用问题。

四、参考链接

说了半天,为什么要用引用计数功能?sp、wp、RefBase的源码深度解析?
请看链接文章内容

Android智能指针RefBase、sp、wp解析

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

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

相关文章

【论文笔记】Prefix-Tuning: Optimizing Continuous Prompts for Generation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Prefix-Tuning: Optimizin…

【Web前端】从回调到现代Promise与Async/Await

异步编程是一种让程序能够在等待某些操作完成的同时继续执行其他任务的关键技术&#xff0c;打破了传统编程中顺序执行代码的束缚。这种编程范式允许开发者构建出能够即时响应用户操作、高效处理网络请求和资源加载的应用程序。通过异步编程&#xff0c;JavaScript 能够在执行耗…

【CSS】“flex: 1“有什么用?

flex 属性的组成 flex 属性是一个复合属性&#xff0c;包含以下三个子属性&#xff1a; flex-grow&#xff1a;决定元素在容器中剩余空间的分配比例。默认值为 0&#xff0c;表示元素不会扩展。当设置为正数时&#xff0c;元素会按照设定比例扩展。flex-shrink&#xff1a;决…

计算机课程管理:Spring Boot与工程认证的协同创新

3系统分析 3.1可行性分析 通过对本基于工程教育认证的计算机课程管理平台实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于工程教育认证的计算机课程管理平…

【SpringBoot】18 上传文件到数据库(Thymeleaf + MySQL)

Git仓库 https://gitee.com/Lin_DH/system 介绍 使用 Thymeleaf 写的页面&#xff0c;将&#xff08;txt、jpg、png&#xff09;格式文件上传到 MySQL 数据库中。 依赖 pom.xml <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --><depende…

Sharding运行模式、元数据、持久化详解

运行模式 单机模式 能够将数据源和规则等元数据信息持久化&#xff0c;但无法将元数据同步至多个Sharding实例&#xff0c;无法在集群环境中相互感知。 通过某一实例更新元数据之后&#xff0c;会导致其他实例由于获取不到最新的元数据而产生不一致的错误。 适用于工程师在本…

挖掘web程序中的OAuth漏洞:利用redirect_uri和state参数接管账户

本文探讨了攻击者如何利用OAuth漏洞&#xff0c;重点是滥用redirect_uri和state参数以接管用户账户。如果redirect_uri参数验证不严&#xff0c;可能会导致未经授权的重定向到恶意服务器&#xff0c;从而使攻击者能够捕获敏感信息。同样&#xff0c;state参数的错误实现可能使O…

Python世界:力扣题解1712,将数组分成三个子数组的方案数,中等

Python世界&#xff1a;力扣题解1712&#xff1a;将数组分成三个子数组的方案数&#xff0c;中等 任务背景思路分析代码实现测试套件本文小结 任务背景 问题来自力扣题目1712. Ways to Split Array Into Three Subarrays&#xff0c;大意如下&#xff1a; A split of an intege…

Java集合基础——针对实习面试

目录 Java集合基础什么是Java集合&#xff1f;说说List,Set,Queue,Map的区别&#xff1f;说说List?说说Set?说说Map&#xff1f;说说Queue?为什么要用集合&#xff1f;如何选用集合&#xff1f; Java集合基础 什么是Java集合&#xff1f; Java集合&#xff08;Java Collect…

基于单片机的客车载客状况自动检测系统(论文+源码)

1系统整体设计 本课题为客车载客状况自动检测系统&#xff0c;在此以STM32单片机为核心控制器&#xff0c;结合压力传感器、红外传感器、蜂鸣器、语音提示模块、继电器、液晶等构成整个客车载客状况自动检测系统&#xff0c;整个系统架构如图2.1所示&#xff0c;在此通过两个红…

渗透测试(socket,namp,scapy)

socket:可以用来实现不同虚拟机或者不同计算机之间的通信。 socket常用函数&#xff1a; sock.bind(host,port) //host可接受client范围&#xff0c;以及连接的端口 sock.listen()//sever开启监听连接 sock.accpet()//返回 sock&#xff0c;addr 用来接受和发送数据 addr…

【mongodb】数据库的安装及连接初始化简明手册

NoSQL(NoSQL Not Only SQL )&#xff0c;意即"不仅仅是SQL"。 在现代的计算系统上每天网络上都会产生庞大的数据量。这些数据有很大一部分是由关系数据库管理系统&#xff08;RDBMS&#xff09;来处理。 通过应用实践证明&#xff0c;关系模型是非常适合于客户服务器…

内网对抗-信息收集篇SPN扫描DC定位角色区域定性服务探针安全防护凭据获取

知识点&#xff1a; 1、信息收集篇-网络架构-出网&角色&服务&成员 2、信息收集篇-安全防护-杀毒&防火墙&流量监控 3、信息收集篇-密码凭据-系统&工具&网站&网络域渗透的信息收集&#xff1a; 在攻防演练中&#xff0c;当完成边界突破后进入内…

OpenWebUI,RAG+外部知识库+AI写文的开源应用

引言 自从去年AI火起来之后&#xff0c;很多人便热衷于寻找适合自用的AI开源项目&#xff0c;把各家大模型API接入到自己的AI程序里&#xff0c;便可以通过AI辅助完成一系列日常任务&#xff0c;比如内容翻译/润色/总结/撰写、格式转换、数据分类、代码分析、角色扮演等等。 …

qt QErrorMessage详解

1、概述 QErrorMessage是Qt框架中用于显示错误消息的一个对话框类。它提供了一个简单的模态对话框&#xff0c;用于向用户显示错误或警告消息。QErrorMessage通常用于应用程序中&#xff0c;当需要向用户报告错误但不希望中断当前操作时。它提供了一个标准的错误消息界面&…

一文了解Android的Doze模式

Android 的 Doze 模式是一项省电功能&#xff0c;主要用于减少设备的功耗&#xff0c;特别是在屏幕关闭且设备长时间未被使用的情况下。Doze 模式在 Android 6.0&#xff08;API Level 23&#xff09;首次引入&#xff0c;并在后续版本中不断改进&#xff0c;以便更智能地管理后…

美团代付微信小程序系统 read.php 任意文件读取漏洞复现

0x01 产品简介 美团代付微信小程序系统是美团点评旗下的一款基于微信小程序技术开发的应用程序功能之一,它允许用户方便快捷地请求他人为自己支付订单费用。随着移动支付的普及和微信小程序的广泛应用,美团作为中国领先的本地生活服务平台,推出了代付功能,以满足用户多样化…

SpringBoot-员工管理系统(1)

目录 一、首页配置 二、国际化 2.1 配置文件编写 2.2 使配置文件生效 2.3 配置页面国际化值 2.4 实现根据按钮自动切换中英文 三、登录拦截器 一、首页配置 1、所有页面的静态资源都需要用thymeleaf接管 2、url使用{}格式 二、国际化 2.1 配置文件编写 1、在resourc…

JavaSE:初识Java(学习笔记)

java是高级语言的面向对象语言 .[最贴近生活.最快速分析和设计程序] 一&#xff0c;计算机语言发展历史 二&#xff0c;Java体系结构 1&#xff0c;JavaSE&#xff08;Java Standard Edition&#xff09; 标准版&#xff0c;定位在个人计算机上的应用 这个版本是Jav…

Android——多线程、线程通信、handler机制

Android——多线程、线程通信、handler机制 模拟网络请求&#xff0c;会阻塞主线程 private String getStringForNet() {StringBuilder stringBuilder new StringBuilder();for (int i 0; i < 100; i) {stringBuilder.append("字符串" i);}try {Thread.sleep(…