Runtime objc4-756.2 isa_t与isa

Posted Jsen_Wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Runtime objc4-756.2 isa_t与isa相关的知识,希望对你有一定的参考价值。

flag: 一年前写的runtime源码博客,今天看objc4已经更新到756.2版本了,接下来一个月内读完并写出对应的博客

前情提要:

runtime的源码版本: objc4-756.2
时间:2019-12-04

Runtime 可能并不是你看到的那样

在搜索引擎中搜索“Runtime”

baidu:

google:

这里边第一页的内容,挨个点进去,所有的人都会拿以下代码说事情:

struct objc_object 
    Class isa  OBJC_ISA_AVAILABILITY;
;

struct objc_class 
    Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif
 OBJC2_UNAVAILABLE;

但是这里边有

#if !__OBJC2__  如果不是Objective-C 2.0
OBJC2_UNAVAILABLE; Objective-C 2.0不可用

那我们现在是什么版本?Objective-C 2.0啊!!!

2006年7月它就发布了,虽然研究老的代码是有参考意义的,但是这么久远的实现应该被时间消逝的无影无踪了吧。有新的为什么不看?

通过Opensource我下载了objc4-723版本,也就是截止2018-11-23最新的runtime开源源码

常用结构体的变化

之前的版本定义:

// ??Class?id
typedef struct objc_class *Class; typedef struct objc_object *id;
// ??????
typedef struct objc_method *Method;
typedef struct objc_ivar *Ivar;
typedef struct objc_category *Category; typedef struct objc_property *objc_property_t;

现在的定义:

typedef struct objc_class *Class; typedef struct objc_object *id;
typedef struct method_t *Method;
typedef struct ivar_t *Ivar;
typedef struct category_t *Category; typedef struct property_t *objc_property_t;

objc_object

// 缩减版代码,public中都是方法,对结构的研究没有啥影响
struct objc_object 
private:
    isa_t isa;

objc_object问题

1,isa_t是个啥?

1.1 定义

// 缩减版代码,我们只留下 arm64下的代码,还有__x86_64__
union isa_t 
    isa_t()  
    isa_t(uintptr_t value) : bits(value)  

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct 
        ISA_BITFIELD;  // defined in isa.h 这里和之前的723版本不同的是换成了宏,但内容本质上没有变化,可阅读行提高
    ;
#endif
;

// 关于ISA_BITFIELD的定义

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \\
      uintptr_t nonpointer        : 1;                                       \\
      uintptr_t has_assoc         : 1;                                       \\
      uintptr_t has_cxx_dtor      : 1;                                       \\
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \\
      uintptr_t magic             : 6;                                       \\
      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  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_BITFIELD                                                        \\
       
        uintptr_t nonpointer        		: 1; 	// 1:64bit 0:32bit \\
        uintptr_t has_assoc         		:1;	 	// 是否有关联引用或者曾经有关联引用\\
        uintptr_t has_cxx_dtor      		: 1; 	// 是否有析构函数\\
        uintptr_t shiftcls         		 	: 33; 	// 所属类的内存地址,isa的指向的\\
        MACH_VM_MAX_ADDRESS 0x1000000000\\
        uintptr_t magic             			: 6; 	// 是否初始化完成\\
        uintptr_t weakly_referenced 	: 1; 	// 是否被弱引用或者曾经被弱引用\\
        uintptr_t deallocating      		: 1; 	// 是否被释放中\\
        uintptr_t has_sidetable_rc  		: 1; 	// 是否引用计数太大超出存储区域\\
        uintptr_t extra_rc          			: 19; 	// 应用计数\\
        
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif

;

  • 1,这是一个union联合体,可以在内部写方法
  • 2,cls/ bits/ isa_t三部分
  • 3,一个描述性联合体,这是isa_t的核心,用它配合bits可以操作整个对象的内存空间

1.2 作用

  • cls是一个Class类型的,所以通过isa_t->cls 就可以获取到当前object的类对象,不用担心消息转发的方式有什么问题。

  • bitsuintptr_tunsigned long别名)类型,在64位系统里,64位,配合一些宏定义做位运算可以方便的获取到对应的信息,比如:在objc_object中有个 Class ISA()方法,内部实现的核心就是return (Class)(isa.bits & ISA_MASK);

  • ISA_MASK这样的宏还有很多,结构中的nonpointer has_assoc 等只可以操作独自负责的内存区域,但是bits可以操作整个对象的内存区域。

  • nonpointer 是对32位处理器的兼容,因为现在都是64位的,在32位的时代,isa就是一个指针地址.而64位的时代中,变成了isa_t,它是一个联合体,里边包含了64位数据上的对应的位操作.就是elif __x86_64__之下定义的这些参数.nonpointer也在其中.

  • 关于isa在64位处理器就变成了联合体的原因,是因为一个指针就占有64位的空间,8个字节,是非常浪费空间的,苹果在这个问题上使用了Tagged Pointer的内存处理技术,在后边我会单独拿出来写一篇博客.

objc_class

定义

//  缩减版代码
struct objc_class : objc_object 
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
    class_rw_t *data()  
        return bits.data();
    

因为objc_class是继承自objc_object的,可以通过ISA()方法获取到对应的元类地址,这里也不用担心原有的消息转发流程问题。

  • superclass 根据注释我们可以看到出来它的作用就是原来isa指针的作用,指向父类的指针,注意这里是类对象的“父类”,最终会一层层指向到根元类,根元类也是一个objc_class对象,他的isa指针指向自己.这样在整个结构就形成了闭环.
  • cachecache_t类型,用来处理已经调用的方法缓存
  • class_data_bits_t 类型的bits是重点,这里边bits和前边isa_t的作用是一样的
  • class_rw_t与之对应的还有一个class_ro_t,前者是class在运行时状态的操作对象,它里边会持有对应的class_ro_t,可读可写。后者是编译时生成的class类型,只读。这两者的详细区别下篇文章解释

常见场景解读

我们经常看到解释isa的一个图

objc_object objc_class在objc4源码中的定义我们已经在上边解读了

对应图中的关系如下:


这样我们可以看出isa指向的是这个对象所属的类,(很多文章说是父类,其实是不准确的).为什么这么说

我们可以看objct.mmsuperclass的定义


+ (Class)superclass 
    return self->superclass;


- (Class)superclass 
    return [self class]->superclass;

所以这句话是不准确的,对于isa指向的描述用指向本对象所属类是比较好的.

以上是关于Runtime objc4-756.2 isa_t与isa的主要内容,如果未能解决你的问题,请参考以下文章

Runtime相关知识

NSObjectClass objc_class objc_objct isa_t

NSObjectClass objc_class objc_objct isa_t

NSObjectClass objc_class objc_objct isa_t

iOS 底层原理 - isa原理

iOS开发runtime学习:一:runtime简介与runtime的消息机制