Runtime之IMP指针,isa指针
要了解 isa 指针先了解下类的定义
在xcode中用快捷键Shift+Cmd+O 搜索objc.h 能看到类的定义:
了解
可以看出:
objc_object:Objective-C对对象的定义, 其质上是结构体对象,其中 isa是它唯一的私有成员变量,即所有对象都有isa指针
Class 是一个 objc_class 结构类型的指针
id是一个 objc_object 结构类型的指针,这也是id可以指向任何对象的原因
SEL(方法选择器)是一个objc_selector结构类型的指针
IMP 先不提
再搜runtime.h
每个对象结构体的首个成员是Class类的变量,该变量定义了对象所属的类,通常称为isa指针
super_class:父类,如果该类已经是最顶层的根类,那么它为NULL。
version:类的版本信息,默认为0
info:供运行期使用的一些位标识。
instance_size:该类的实例变量大小
ivars:成员变量的数组
struct objc_method_list **methodLists OBJC2_UNAVAILABLE : 方法列表,类目就是通过它添加方法的
struct objc_cache *cache OBJC2_UNAVAILABLE : 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在methodLists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE : 协议链表
isa 指针优化(NONPOINTER_ISA)
用 64 bit 存储一个内存地址显然是种浪费,毕竟很少有那么大内存的设备。于是可以优化存储方案,用一部分额外空间存储其他内容。isa 指针第一位为 1 即表示使用优化的 isa 指针,这里列出不同架构下的 64 位环境中 isa 指针结构:
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
#if SUPPORT_NONPOINTER_ISA
# if __arm64__
# define ISA_MASK 0x00000001fffffff8ULL
# define ISA_MAGIC_MASK 0x000003fe00000001ULL
# define ISA_MAGIC_VALUE 0x000001a400000001ULL
struct {
uintptr_t indexed : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000
uintptr_t magic : 9;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 19;
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
};
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x0000000000000001ULL
# define ISA_MAGIC_VALUE 0x0000000000000001ULL
struct {
uintptr_t indexed : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 14;
# define RC_ONE (1ULL<<50)
# define RC_HALF (1ULL<<13)
};
# else
// Available bits in isa field are architecture-specific.
# error unknown architecture
# endif
// SUPPORT_NONPOINTER_ISA
#endif
};
SUPPORT_NONPOINTER_ISA 用于标记是否支持优化的 isa 指针,其字面含义意思是 isa 的内容不再是类的指针了,而是包含了更多信息,比如引用计数,析构状态,被其他 weak 变量引用情况。判断方法也是根据设备类型:
#if !__LP64__ || TARGET_OS_WIN32 || TARGET_IPHONE_SIMULATOR || __x86_64__
# define SUPPORT_NONPOINTER_ISA 0
#else
# define SUPPORT_NONPOINTER_ISA 1
#endif
isa指针会判断是否支持 TaggedPointer 支持会直接将其指针值作为引用计数返回
TaggedPointer 就是一种优化方式,当承载内容小于8字节时,指针直接储存承载内容
关于Tagged Pointer 这里有详细介绍
http://www.infoq.com/cn/articles/deep-understanding-of-tagged-pointer/
如果当前设备是 64 位环境并且使用 Objective-C 2.0(5s之后就都是64位),那么“一些”对象会使用其 isa 指针的一部分空间来存储它的引用计数;否则 Runtime 会使用一张散列表来管理引用计数
64位中isa 指针中变量对应的含义:
associate object : 关联对象
IMP 指针
SEL会依据方法名生成唯一的表示作为key ,便于查找
IMP指针是指向实现函数的指针,通过SEL取得IMP,objc_msgSend来执行实现方法
objc_msgSend函数在执行方法时不会直接在 isa 指针指向的类的方法列表中遍历查找能够响应的方法,因为每次都要查找效率太低了,而是优先在缓存(方法列表)中查找,若是找不到再沿着继承体向上查找。每次匹配到的结果会缓存在"快速映射表"里,来提高效率,同时objc_msgSend函数用到了"尾调用优化技术",来节约资源,感兴趣可以了解下
https://en.wikipedia.org/wiki/Tail_call
http://kb.cnblogs.com/page/518771/
//引用文章
http://www.cocoachina.com/ios/20151209/14636.html
http://www.cocoachina.com/ios/20150717/12623.html
http://www.cnblogs.com/ioshe/p/5489086.html
Runtime之IMP指针,isa指针的更多相关文章
- iOS 认识runtime 中的三个指针 isa , IMP , SEL
runtime中函数调用经常被提及的三个概念 isa,IMP,SEL 一 isa:是类指针,之所以说isa是指针是因为Class其实是一个指向objc_class结构体的指针,而isa 是它唯一的私 ...
- runtime运行时,类、对象、isa指针
先查看一段OC源码,关于类的定义: /// An opaque type that represents an Objective-C class. typedef struct objc_class ...
- isa指针
转载自 http://www.cnblogs.com/zhangdashao/p/4438540.html 可以去这里看详细的. 每个Objective-C对象都有一个隐藏的数据结构,这个数据结构是O ...
- 关于oc运行时 isa指针详解
Cocoa框架是iOS应用程序的基础,了解Cocoa框架,对开发iOS应用有很大的帮助. 1.Cocoa是什么? Cocoa是OS X和 iOS操作系统的程序的运行环境. 是什么因素使一个程序成为Co ...
- OC self super isa指针
self指针: self是oc面向对象设计中的一个特殊指针,相当于java中的this,但是比this强大,this只能访问实例对象的相关方法和成员变量,或者说this只代表实例对象: self不仅可 ...
- iOS isa指针
在Objective-C中,任何类的定义都是对象.类和类的实例没有任何本质上的区别.任何对象都有isa指针. isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,它指向对象的类,而C ...
- 位域-isa指针
一.isa指针结构 union isa_t { isa_t() { } isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bi ...
- 神经病院Objective-C Runtime入院第一天——isa和Class
前言 我第一次开始重视Objective-C Runtime是从2014年11月1日,@唐巧老师在微博上发的一条微博开始. 这是sunnyxx在线下的一次分享会.会上还给了4道题目. 这4道题 ...
- C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用
类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...
随机推荐
- Android AOSP 编译sdk
首先你要有AOSP 工程. 然后执行下面的命令编译sdk. //运行下面的命令得到编译环境 source build/envsetup.sh lunch sdk make sdk 最后文件输出在哪个位 ...
- Centos7 下安装以及使用mssql
Centos7下安装以及使用Mssql,在这下面玩,主要是发现linux环境下的mysql非常的小,小到只有169M,这在windows上面,动撤几个G的安装文件,会让你直接打消使用MSSQL的勇气, ...
- 06003_redis在Linux上的安装
1.redis-3.0.0.tar.gz下载链接:redis-3.0.0.tar.gz下载 密码:wpbu 2.安装redis编译的c环境,yum install gcc-c++ : 3.将redis ...
- 创龙DSP6748开发板LED闪烁-第一篇
1. 首先看下DSP6748的GPIO寄存器的文档,先看下框图,有这个框图,一目了然,输入和输出很清楚 2. 看下寄存器部分,对应上面的图,问题在于,DSP6748有多少个GPIO?最多144个,下一 ...
- 利尔达仿真器加有人CC3200模块USR-C322上电测试
1. 使用利尔达的CC3200底板仿真器对有人CC3200模块USR-C322进行烧写,测试. 2. 连接的接口,需要连接6根线,如下,供电测试,第一波测试,输入+++回复a,然后在输入a,返回+OK ...
- MySQL高级-MySQL安装
1.mysql安装 检查系统是否安装过mysql 查询命令:rpm -qa|grep -i mysql 删除命令:rpm -e RPM软件包名(该名字是上一个命令查出来的名字) 安装命令:rpm -i ...
- Xuan.UWP.Framework(2)
上一章主要介绍了Xuan.UWP.Framework.ImageLib的基本用法,这一章具体来看些Xuan.UWP.Framework.ImageLib的使用. 一.首先看下Xuan.UWP.Fram ...
- Java图片转字符
很久都没有更新博客了,昨天下午一个朋友问我能不能将一张图片转换成字符画,然后我想我这个朋友不知道,也许有的朋友以不知道,我就简单的分享一下 package com.xsl.zhuanhuan; imp ...
- 用python读取配置文件config.ini
还在学习中...写的有点凌乱 感觉还是应该先学会读取配置文件才行,把一些经常需要修改的但是又经常需要用到的参数放到配置文件中方便使用(我是这么觉得的) 首先是config.ini的存放位置,我们把它放 ...
- Selenium 入门到精通系列:四
Selenium 入门到精通系列 PS:鼠标右键.鼠标悬停.键盘操作方法 例子 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019 ...