美文网首页
五、isa走位 和 类结构分析

五、isa走位 和 类结构分析

作者: KB_MORE | 来源:发表于2020-09-09 10:21 被阅读0次

先附上经典图, 表示敬畏😸


看了好多遍的isa走位图
isa的走位
  1. 实例对象(Instance of Subclass)的isa 指向 类(class)

  2. 类对象(class) isa 指向 元类(Meta class)

  3. 元类(Meta class)的isa 指向 根元类(Root metal class

  4. 元类(Root metal class)isa 指向它自己本身,形成闭环,这里的根元类就是NSObject

superclass(继承关系)走位
  1. 类(subClass) 继承自 父类(superClass)

  2. 父类(superClass) 继承自 根类(RootClass ),此时的 根类是指 NSObject

  3. 根类 继承自 nil,所以 根类NSObject可以理解为万物起源

  4. 子类元类(metal SubClass) 继承自 父类元类(metal SuperClass)

  5. 父类元类(metal SuperClass ) 继承自 根元类(Root metal Class

  6. 根元类(Root metal Class) 继承于 根类(Root class ),此时的 根类是指 NSObject

  • 【注意】 实例对象之间 没有 继承关系,之间有继承关系 *

分析

LGPerson

@interface LGPerson : NSObject
+ (void)sayHello;
- (void)say666;
@end
#import "LGPerson.h"

@interface LGPerson ()
@property (nonatomic, copy) NSString *name;
@end
@implementation LGPerson{
    NSString *_hobby;
}
+ (void)sayHello{
    NSLog(@"sayHello");
}
- (void)say666{
    NSLog(@"say666");
}
@end

LGTeacher 继承LGPerson

#import "LGPerson.h"

@interface LGTeacher : LGPerson

@end

#import "LGTeacher.h"

@implementation LGTeacher

@end

        LGPerson *person = [LGPerson alloc];
        LGTeacher  *teacher = [LGTeacher alloc];

        NSLog(@"Hello, Person!  %@",person);
        NSLog(@"Hello, Teacher!  %@",teacher);
图片.png
图片.png

p/x : 打印person首地址
x/4gx :查看person内存情况: 第一个为isa指针地址
指针地址 & 0x00007ffffffffff8ULL: 获取类信息
isa走位
person -> LGPerson ->LGPerson(元类)->NSObject(根元类)->NSObject

类结构分析

LGPerson继承至NSObject

@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
    Class isa  OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}

NSObject的底层编译是NSObject_IMPL结构体,
其中 Classisa指针的类型,是由objc_class定义的类型,
objc_class是一个结构体。在iOS中,所有的Class都是以 objc_class为模板创建的`

struct NSObject_IMPL {
    Class isa;
};
typedef struct objc_class *Class;

查看源码已经被废除

图片.png
不过可以根据最后一行注释(/* Use Class instead of struct objc_class * */
)找到目前所用的class 图片.png 同理可查出 objc_class的父类objc_object 图片.png

【问题】objc_class 与 objc_object 有什么关系?

通过上述的源码查找以及main.cpp中底层编译源码,有以下几点说明:

  • 结构体类型objc_class 继承自objc_object类型,其中objc_object也是一个结构体,且有一个isa属性,所以objc_class也拥有了isa属性

  • mian.cpp底层编译文件中,NSObject中的isa在底层是由Class 定义的,其中class的底层编码来自 objc_class类型,所以NSObject也拥有了isa属性

  • NSObject 是一个类,用它初始化一个实例对象objc,objc 满足 objc_object 的特性(即有isa属性),主要是因为isa 是由 NSObjectobjc_class继承过来的,而objc_class继承自objc_objectobjc_objectisa属性。所以对象都有一个 isa,isa表示指向,来自于当前的objc_object

  • objc_object(结构体) 是 当前的 根对象所有的对象都有这样一个特性 objc_object,即拥有isa属性

【百度面试题】objc_object 与 对象的关系

  • 所有的对象 都是以 objc_object为模板继承过来的

  • 所有的对象 是 来自 NSObject(OC) ,但是真正到底层的 是一个objc_object(C/C++)的结构体类型

【总结】 objc_object对象关系继承关系

总结

  • 所有的对象 + + 元类 都有isa属性

  • 所有的对象都是由objc_object继承来的

  • 简单概括就是万物皆对象,万物皆来源于objc_object,有以下两点结论:

    • 所有以 objc_object为模板 创建的对象,都有isa属性

    • 所有以objc_class为模板,创建的,都有isa属性

  • 在结构层面可以通俗的理解为上层OC底层对接

    • 下层是通过 结构体 定义的 模板,例如objc_class、objc_object
    • 上层 是通过底层的模板创建的 一些类型,例如CJLPerson

objc_class、objc_object、isa、object、NSObject等的整体的关系,如下图所示

image

到底类中有哪些信息呢?

根据前文提及的objc_class 的新版定义(objc4-781版本)如下,有以下几个属性

struct objc_class : objc_object {
    // Class ISA; //8字节
    Class superclass; //Class 类型 8字节
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
    //....方法部分省略,未贴出
}

可以通过地址偏移获取bits里面的类信息, 首先我们还需要知道地址的偏移量

  • isa: objc继承至objc_object, 所以也包含一个isa指针,继承自objc_object的isa,占 8字节

  • superclass 属性:Class类型,Class是由objc_object定义的,是一个指针,占8字节

  • cache属性:简单从类型class_data_bits_t目前无法得知,而class_data_bits_t是一个结构体类型,结构体的内存大小需要根据内部的属性来确定,而结构体指针才是8字节

  • bits属性:只有首地址经过上面3个属性的内存大小总和的平移,才能获取到bits

struct cache_t {
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
    explicit_atomic<struct bucket_t *> _buckets; // 是一个结构体指针类型,占8字节
    explicit_atomic<mask_t> _mask; //是mask_t 类型,而 mask_t 是 unsigned int 的别名,占4字节
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
    explicit_atomic<uintptr_t> _maskAndBuckets; //是指针,占8字节
    mask_t _mask_unused; //是mask_t 类型,而 mask_t 是 uint32_t 类型定义的别名,占4字节
    
#if __LP64__
    uint16_t _flags;  //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节
#endif
    uint16_t _occupied; //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节

获取bits

所以有上述计算可知,想要获取bits的中的内容,只需通过类的首地址平移32字节即可

以下是通过lldb命令调试的过程


图片.png

也可以打印属性列表


图片.png

以及存在ro里面的ivars


图片.png class_rw_t中的一部分重要信息 图片.png

相关文章

  • 五、isa走位 和 类结构分析

    先附上经典图, 表示敬畏? isa的走位 实例对象(Instance of Subclass)的isa 指向 类(...

  • iOS 类的结构分析(下)

    在上一篇 iOS 类的结构分析(上) 分析了类的结构、isa 的走位以及类的内存分布(属性列表&实例方法列表),这...

  • isa相关的经典面试题分析

    前言 书接上回类的结构分析,我们得知isa指针的走位:对象 --> 类 --> 元类 --> 根元类-->根元类 ...

  • 五、isa 和类结构分析

    主要内容:围绕类展开探索一、isa 走位 1.类的分析  2.元类  3.isa走位  4.superClass ...

  • iOS 类结构分析

    前言 通过本篇文章可以了解1.isa的走位2.类结构的分析3.什么是元类4.supclass的走位5.objc_c...

  • iOS-底层原理 :类 & isa 经典问题分析

    今天主要研究isa走位 & 继承关系 & 类结构 相关的问题的分析 类存在几份? 由于类的信息在内存中永远只存在一...

  • Cache_t的结构和原理

    在之间的文章里我们分析了isa的指向和结构isa结构分析,分析了bits类的结构分析,在这篇文章里,我们来分析ob...

  • 类结构分析

    这片文章主要分析的是类的结构以及对象-类-元类-根元类之间的走位. 一. isa的指向以及类之间的关系 准备工作定...

  • 类的结构分析

    前言 书接上回isa结构分析,我们得知,对象的isa指针指向类,确切的说,是isa指针的shiftcls位域中指向...

  • isa指针指向和类结构分析

    isa指针指向和类结构分析 isa指向图 经典的isa指向图 从这张图能总结出类继承自父类,父类继承于NSObje...

网友评论

      本文标题:五、isa走位 和 类结构分析

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