12 runtime之isa详解

作者: zysmoon | 来源:发表于2020-01-20 14:41 被阅读0次
    序言
    • Objective-C是一门动态性比较强的编程语言,跟C、C++等语言有着很大的不同
    • Objective-C的动态性是由Runtime API来支撑的
    • Runtime API提供的接口基本都是C语言的,源码由C\C++\汇编语言编写
    位运算和共用体
    位运算

    程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。

    C++提供了6种位运算符来进行位运算操作:

    • & 按位与
    • | 按位或
    • ^ 按位异或
    • ~ 按位取反
    • << 左移(左边消失,右边补0)
    • 右移(右边消失,左边补符号位)

    位运算的操作数是整数类型或字符型.

    1.按位与&运算

    相同为一

    & 运算常常用来将某变量的某些位清0
    & 也常用于二进制取位操作

    2.按位或|运算

    有一则一

    |运算通常用于二进制特定位上的强制置1

    3.按位异或^运算

    ^运算通常用于对二进制的特定一位进行取反操作

    共用体

    共用体把几种不同数据类型的变量存放在同一块内存里。共用体中的变量共享同一块内存。

    定义共用体类型变量的一般形式:

    union 共用体名
    {
        成员列表
    }变量列表;
    
    

    union的主要特征有

    • union中可以定义多个成员,union的大小由最大的成员的大小决定;
    • union成员共享同一块大小的内存,一次只能使用其中的一个成员;
    • 对union某一个成员赋值,会覆盖其他成员的值(但前提是成员所占字节数相同,当成员所占字节数不同时只会覆盖相应字节上的值,比如对char成员赋值就不会把整个int成员覆盖掉,因为char只占一个字节,而int占四个字节);
    • union量的存放顺序是所有成员都从低地址开始存放的。
    一 isa详解
    • 要想学习Runtime,首先要了解它底层的一些常用数据结构,比如isa指针
    • 在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址
    • 从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息
    1653926-c370f62a02d018a9.png
    • isa结构体
    1653926-d5c06f4e3d74f16d.png

    实例代码如下 - 一定需要用真机进行调试

    #import <Foundation/Foundation.h>
    @interface CSPerson : NSObject
    @end
    
    

    创建一个对象并且断点调试,输出 isa 值

    1653926-e01cf48ffe4983a6.png 1653926-2cf9348dca800c9f.png 1653926-5614583aded360d5.png
    • 接下来我们创建一些关联对象和弱引用对象
    1653926-e07d2bc33e50dffe.png 1653926-75250603d4bc04d7.png 1653926-c72126d4fabe70cb.png 1653926-b6d867514a407057.png
    isa参数详解
    • nonpointer:
      0,代表普通的指针,存储着Class、Meta-Class对象的内存地址
      1,代表优化过,使用位域存储更多的信息
    • has_assoc:是否有设置过关联对象,如果没有,释放时会更快
    • has_cxx_dtor:是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
    • shiftcls:存储着Class、Meta-Class对象的内存地址信息
    • magic:用于在调试时分辨对象是否未完成初始化
    • weakly_referenced:是否有被弱引用指向过,如果没有,释放时会更快
      • deallocating:对象是否正在释放
    • extra_rc:里面存储的值是引用计数器减1
    • has_sidetable_rc:引用计数器是否过大无法存储在isa中
      如果为1,那么引用计数会存储在一个叫SideTable的类的属性中
    为什么要&ISA_MASK来获取类或元类的地址

    因为从arm64位开始,isa里面存储各种信息,是一个共用体,其中shiftcls 33位才是用来存放地址。通过&ISA_MASK就可以将33位的地址值取出来。

    无论是实例对象,还是类对象,还是元类对象,他们的地址最后一位要么是0,要么是8,因为他们的地址是isa & ISA_MASK,又因为ISA_MASK最后3位都是0,所以导致他们的地址最后3位也永远是0,所以最后一位要么是0(0000 0000),要么是8(0000 0100)


    本文参考:
    路飞_Luck (https://www.jianshu.com/p/07f7b96bb03f)
    以及借鉴MJ的教程视频
    非常感谢.


    项目连接地址 - runtime_union_mask

    相关文章

      网友评论

        本文标题:12 runtime之isa详解

        本文链接:https://www.haomeiwen.com/subject/pbdjfqtx.html