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

Objective-C 中的 isa 不再是简单的结构体指针

了解 Objective-C 中的 isa 指针内存结构

在 Objective-C 中,isa 指针是对象和类之间的重要桥梁。它不仅帮助运行时系统识别对象的类型,还参与了一些内存和性能优化。本文将深入讲解 isa 指针的内存结构,包括其在早期和现代实现中的演变。

什么是 isa 指针?

每个 Objective-C 对象都有一个 isa 指针,它指向对象的类对象。类对象本身也是一个对象,它的 isa 指针指向一个元类对象(meta-class)。元类对象存储类方法,并且其 isa 指针最终指向根元类(通常是 NSObject 的元类)。

早期的 isa 指针结构

在早期的 Objective-C 实现中,isa 指针简单地指向类对象的结构体。以下是一个典型的早期实现示例:

struct objc_object {Class isa; // 指向类对象的指针
};typedef struct objc_class *Class; // Class 的本质是 objc_class 类型的结构体指针
struct objc_class {Class isa; // 指向元类对象的指针Class super_class; // 指向父类对象的指针// 其他类相关的元数据
};

在这种结构下:

  • 对象的 isa 指针指向类对象。
  • 类对象的 isa 指针指向元类对象。
  • 元类对象的 isa 指针指向根元类对象。

现代 isa 指针结构

在 64 位系统和现代 Objective-C 运行时中,isa 指针被重新设计为一个更复杂的联合体(union isa_t),它不仅包含指向类对象的指针,还包含其他标志位和信息,以优化内存使用和性能。以下是 isa_t 结构的一个简化示例:

union isa_t {isa_t() { }isa_t(uintptr_t value) : bits(value) { }Class cls; // 指向类对象的指针uintptr_t bits; // 包含位域信息的位模式struct {uintptr_t nonpointer        : 1;  // 是否启用优化的 non-pointer isauintptr_t has_assoc         : 1;  // 是否有关联对象uintptr_t has_cxx_dtor      : 1;  // 是否有 C++ 析构函数uintptr_t shiftcls          : 33; // 类指针(经过位移和压缩)uintptr_t magic             : 6;  // 调试用的魔数uintptr_t weakly_referenced : 1;  // 是否被弱引用uintptr_t deallocating      : 1;  // 是否正在释放uintptr_t has_sidetable_rc  : 1;  // 是否有辅助引用计数表uintptr_t extra_rc          : 19; // 额外的引用计数};
};

结构字段解释

  • nonpointer:指示 isa 是否为非指针类型(优化内存布局,存储额外信息)。
  • has_assoc:对象是否有关联引用(Associative References)。
  • has_cxx_dtor:对象是否有 C++ 析构函数,需要调用析构函数。
  • shiftcls:类指针,存储对象的类信息(经过位移和压缩)。
  • magic:用于调试和运行时验证的魔数(magic number)。
  • weakly_referenced:对象是否被弱引用指向。
  • deallocating:对象是否正在被释放。
  • has_sidetable_rc:对象的引用计数是否存储在辅助表(Side Table)中。
  • extra_rc:额外的引用计数,用于优化内存占用。

引用计数的存储与管理

在早期的 Objective-C 实现中,引用计数通常作为对象结构的一部分直接存储在对象中。例如:

struct objc_object {Class isa; // 指向类对象的指针uintptr_t retainCount; // 引用计数
};

在现代的 Objective-C 运行时中,引用计数通过 isa 指针的优化结构和 Side Table 辅助数据结构进行管理。

  • Inline Reference Counting:部分引用计数信息被存储在 isa 指针的优化结构中,例如 extra_rc 字段。
  • Side Table:当引用计数超出 isa 指针所能表示的范围时,引用计数会存储在一个称为 Side Table 的辅助数据结构中。

Modern isa 指针的优势

  • 内存优化:通过将更多信息(如引用计数、标志位)存储在 isa 指针中,减少了对其他内存区域的访问,提升了性能。
  • 性能提升:减少了内存读取操作,因为可以在一次内存读取中获取更多信息。
  • 更丰富的元数据:可以包含更多运行时信息,有助于提高运行时的灵活性和效率。

使用示例

虽然开发者在日常编码中通常不直接与 isa 指针交互,但理解其结构对于调试和优化性能是有帮助的。以下是一个使用示例,通过访问对象的类信息来显示对象的类型:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>@interface MyClass : NSObject
@end@implementation MyClass
@endint main(int argc, const char * argv[]) {@autoreleasepool {MyClass *obj = [[MyClass alloc] init];Class cls = object_getClass(obj);NSLog(@"Class name: %s", class_getName(cls));// 访问 isa 指针信息(需要通过运行时函数)NSLog(@"isa pointer: %p", *(uintptr_t *)obj);}return 0;
}

总结

isa 指针在 Objective-C 运行时中扮演着重要角色,从早期简单的指向类对象,到现代复杂的 isa_t 结构,它帮助优化了内存使用和性能。理解 isa 指针的演变和内存结构,可以帮助我们更好地掌握 Objective-C 的运行时机制,并编写高效的代码。

希望这篇文章能帮助你深入了解 Objective-C 中 isa 指针的内存结构。如有任何问题或建议,欢迎留言讨论。

相关文章:

Objective-C 中的 isa 不再是简单的结构体指针

了解 Objective-C 中的 isa 指针内存结构 在 Objective-C 中&#xff0c;isa 指针是对象和类之间的重要桥梁。它不仅帮助运行时系统识别对象的类型&#xff0c;还参与了一些内存和性能优化。本文将深入讲解 isa 指针的内存结构&#xff0c;包括其在早期和现代实现中的演变。 …...

中介子方程五十二

XXFXXaXnXaXXαXLXyXXWXuXeXKXXiXyXΣXXΣXXVXuXhXXWXηXXiXhXXpXiXXpXXbXXpXXiXpXXhXiXXηXWXXhXuXVXXΣXXΣXyXiXXKXeXuXWXXyXLXαXXaXnXaXXFXXaXnXaXXαXLXyXXWXuXeXKXXiXyXΣXXΣXXVXuXhXXWXηXXiXhXXpXiXXpXXbXXpXXiXpXXhXiXXηXWXXhXuXVXXΣXXΣXyXiXXKXeXuXWXXyXLXαXXa…...

LabVIEW在半导体自动化测试中的应用

半导体制造的复杂性和精密度要求极高&#xff0c;每一个生产步骤都需要严格的控制和监测。自动化测试设备在半导体制造中起到了关键作用&#xff0c;通过精密测量和数据分析&#xff0c;确保产品质量和生产效率。本文介绍如何使用LabVIEW结合研华硬件&#xff0c;开发一个用于半…...

政安晨:【Keras机器学习示例演绎】(五十三)—— 使用 TensorFlow 决策森林进行分类

目录 简介 设置 准备数据 定义数据集元数据 配置超参数 实施培训和评估程序 实验 1&#xff1a;使用原始特征的决策森林 检查模型 实验 2&#xff1a;目标编码决策森林 创建模型输入 使用目标编码实现特征编码 使用预处理器创建梯度提升树模型 训练和评估模型 实验…...

51单片机:电脑通过串口控制LED亮灭(附溢出率和波特率详解)

一、功能实现 1.电脑通过串口发送数据&#xff1a;0F 2.点亮4个LED 二、注意事项 1.发送和接受数据的文本模式 2.串口要对应 3.注意串口的波特率要和程序中的波特率保持一致 4.有无校验位和停止位 三、如何使用串口波特率计算器 1.以本程序为例 2.生成代码如下 void Uar…...

Java中的消息中间件选择与比较

Java中的消息中间件选择与比较 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在分布式系统中&#xff0c;消息中间件是一种关键组件&#xff0c;它能帮助不同…...

react基础语法,模板语法,ui渲染,jsx,useState状态管理

创建一个react应用 这里使用create-react-app的脚手架构建项目&#xff08;结构简洁&#xff0c;基于webpack-cli&#xff09;&#xff0c; npx create-react-app [项目名称] 使用其他脚手架构建项目可以参考&#xff1a;react框架&#xff0c;使用vite和nextjs构建react项目…...

OJ-0710

示例1 input 4 100 200 300 5001 21 32 4output700100 200 500 300 示例2 input 4 100 200 300 500 1 2 1 3 1 4output1100100 200500300 示例3 input 6 100 200 300 400 300 550 1 2 1 3 1 4 2 5 2 6output1050100 200 300600 300400 import java.util.ArrayList; im…...

人工智能在自动驾驶中的目标检测研究

摘要 随着自动驾驶技术的快速发展&#xff0c;视觉识别作为核心技术之一&#xff0c;扮演着至关重要的角色。本文旨在探讨人工智能如何通过视觉识别在自动驾驶中进行目标检测。我们将详细讨论目标检测的基本原理、常用算法、最新进展、已有的开源项目及其在自动驾驶中的应用和…...

【合并两个有序数组】

合并两个有序数组 一、题目二、普通解法三、双指针 一、题目 二、普通解法 先合并后排序 补充:js合并数组方法详见https://blog.csdn.net/ACCPluzhiqi/article/details/131702269?fromshareblogdetail js排序方法见http://t.csdnimg.cn/wVCOP 时间复杂度&#xff1a;O(mn)…...

链表 OJ(一)

移除链表元素 题目连接&#xff1a; https://leetcode.cn/problems/remove-linked-list-elements/description/ 使用双指针法&#xff0c;开始时&#xff0c;一个指针指向头节点&#xff0c;另一个指针指向头节点的下一个结点&#xff0c;然后开始遍历链表删除结点。 这里要注…...

《Linux与Windows文件系统的区别》

Linux与Windows文件系统的区别 在计算机操作系统领域&#xff0c;Linux和Windows是两种广泛使用的操作系统&#xff0c;它们在文件系统方面有许多显著的差异。这篇博客将详细介绍这两种操作系统文件系统的区别&#xff0c;帮助读者更好地理解它们各自的特点和优势。 类别Linu…...

批量修改Git历史commit信息中的username

之前很长一段时间GitHub上的提交都在使用工作账户, 导致私人仓库中的提交者比较混乱. 在StackOver里面找到了一个bash脚本可以批量修改username, 在这里记录一下. 修改的步骤一共两步: 执行修改脚本将本地修改同步到Git服务器 首先我们来看脚本: #!/bin/shgit filter-branch…...

LabVIEW与ABB工业机器人据监控

​1. 前言 随着工业自动化的发展&#xff0c;工业机器人在制造业中的应用越来越广泛。为了实现对工业机器人的高效监控和控制&#xff0c;本文介绍了利用OPC&#xff08;OLE for Process Control&#xff09;服务器将ABB工业机器人与LabVIEW连接起来的解决方案。通过OPC服务器…...

c++栈内存和堆内存的基本使用

c栈内存和堆内存的基本使用 #include <iostream>// 定义一个简单的结构体 struct Person {std::string name;int age; };int main() {// 栈内存分配int a 10; // 基本数据类型的栈内存分配Person person; // 结构体的栈内存分配person.name "John";person.a…...

快速入门,springboot知识点汇总

学习 springboot 应该像学习一门编程语言一样&#xff0c;首先要熟练掌握常用的知识&#xff0c;而对于不常用的内容可以简单了解一下。先对整个框架和语言有一个大致的轮廓&#xff0c;然后再逐步补充细节。 前序: Spring Boot 通过简化配置和提供开箱即用的特性&#xff0c…...

Ubuntu20.04系统非root用户安装GAMIT10.71

&#xff08;测试环境&#xff1a;20240701升级包和20240701数据&#xff0c;解算通过&#xff09; QQ:8212714 群&#xff1a;302883438群文件&#xff08;source安装包20240701升级包&#xff09; 1、首先在计算机中安装VMware Workstation 16 Pro。建议&#xff1a;分配…...

stm32 开发板可以拿来做什么?

STM32开发板可以用来做许多不同的事情&#xff0c;具体取决于您的应用需求和编程能力。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕设800套和语言类教学&#xff0c;敲个22就可…...

latex英文转中文word,及一些latex相关工具分享

前言&#xff1a;想要转换latex生成的英文pdf文件为中文word文件 一、主要步骤 1、文字翻译&#xff1a;直接使用谷歌翻译等辅助将英文翻译成中文即可&#xff1b; 支持英文pdf文件全文翻译&#xff0c;再用迅捷PDF转换器之类的转成word&#xff0c;再手动调整。 https://app…...

EasyOCR: 简单易用的多语言OCR工具

EasyOCR: 简单易用的多语言OCR工具 1. 什么是EasyOCR?2. 使用场景3. 基本使用方法安装示例代码代码解释 4. 结语 1. 什么是EasyOCR? EasyOCR是一个基于Python的开源光学字符识别(OCR)工具,它支持80多种语言的文本识别。该项目由JaidedAI开发,旨在提供一个简单易用但功能强大…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...