美文网首页
isa结构分析

isa结构分析

作者: 奶牛的奶糖 | 来源:发表于2020-09-18 00:45 被阅读0次
image.png
(lldb) memory read person
0x600002e264f0: d0 e7 de 03 01 00 00 00 61 62 00 00 14 00 00 00  ........ab......
0x600002e26500: 38 c0 de 03 01 00 00 00 58 c0 de 03 01 00 00 00  8.......X.......
(lldb) x/6gx person     (x:打印内存格式  4: 打印4段   g: 打印   x: 16进制打印16位    w:打印16进制的8位)
0x600002e264f0: 0x0000000103dee7d0 0x0000001400006261
0x600002e26500: 0x0000000103dec038 0x0000000103dec058
0x600002e26510: 0x0000000000000000 0x0000000000000000\
OC对象的本质

在一个内中添加一个私有类,在main.m文件中添加一个LGPerson类

@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@end

@implementation LGPerson
@end

使用clang将main.m编译为main.cpp

cd进入工程目录下
clang -rewrite-objc main.m -o main.cpp

会看到在main.m文件同目下生成一个main.cpp文件,打开main.cpp文件,直接查找LGPerosn相关的

//我们可以发现LGPerson在底层其实就是struct结构体
extern "C" unsigned long OBJC_IVAR_$_LGPerson$_name;
struct LGPerson_IMPL {
    struct NSObject_IMPL NSObject_IVARS; // isa
    NSString *_name;
};

// @property (nonatomic, copy) NSString *name;
/* @end */


// @implementation LGPerson
//get方法
static NSString * _I_LGPerson_name(LGPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_name)); }
// 所有的set方法都会通过objc_setProperty去实现
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
//set方法
static void _I_LGPerson_setName_(LGPerson * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct LGPerson, _name), (id)name, 0, 1); }
// @end

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_qh_pdfhk2010yz_2g4kgb84zmmr0000gn_T_main_8452c9_mi_0);
    }
    return 0;
}

objc_setProperty相当于一个通用接口,工厂模式,通用一个模板方法去给属性赋值

objc_setProperty实现

image.png
alloc  - >  _objc_rootAlloc  -> callAlloc  -> ISA()
1.alloc
+ (id)alloc {
    return _objc_rootAlloc(self);
}

2._objc_rootAlloc
id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

3.callAlloc
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && !cls)) return nil;
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}

4. ISA
inline Class 
objc_object::ISA() 
{
    ASSERT(!isTaggedPointer()); 
#if SUPPORT_INDEXED_ISA
    if (isa.nonpointer) {
        uintptr_t slot = isa.indexcls;
        return classForIndex((unsigned)slot);
    }
    return (Class)isa.bits;
#else
    return (Class)(isa.bits & ISA_MASK);
#endif
}


5. isa_t
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
    };
#endif
};

由此可见 isa就是class类型的指针,ISA里面是一个联合体,联合体的每个对象互斥, 每个对象都有一个isa指针, 一个指针8字节, 一个字节占8位, 所占64位
进入isa_t的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)
  • nonpointer:表示是否对 isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地址,isa 中包含了类信息、对象的引用计数等
  • has_assoc:关联对象标志位,0没有,1存在
  • has_cxx_dtor:该对象是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑, 如果没有,则可以更快的释放对象
  • shiftcls存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位用来存储类指针。
  • magic用于调试器判断当前对象是真的对象还是没有初始化的空间
  • weakly_referenced志对象是否被指向或者曾经指向一个 ARC 的弱变量,
    没有弱引用的对象可以更快释放。
  • deallocating标志对象是否正在释放内存
  • has_sidetable_rc当对象引用技术大于 10 时,则需要借用该变量存储进位
  • extra_rc:当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。

isa 是通过isa_t中的shiftclas这个属性存储了类信息, 通过initInstanceIsa方法把isa和cls之间进行了绑定

image.png

iOS是小端模式存储, 从低位开始, ①.如果要读取shfitclas则需要先右移3位,末尾抹零,左边则补齐3位,加上之前左边的17位,② 高位需要左移20位, 右边抹零, ③最后还原位置,右移17位

image.png

相关文章

  • Cache_t的结构和原理

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

  • iOS - isa的初始化&指向分析

    isa结构及初始化分析 什么是isa,首先我们先看一下isa的结构: 由源码我们可以看出:isa的本质就是一个联合...

  • isa结构分析

    什么是对象? 为了了解Objective-C类在底层会编译成什么,我们先新建一个类DebugPerson。 测试类...

  • isa结构分析

    isa结构分析 OC对象的本质 clang命令 把oc类编译成c++文件,对象在底层编译成struct 联合体(共...

  • isa结构分析

    OC对象的本质 在一个内中添加一个私有类,在main.m文件中添加一个LGPerson类 使用clang将main...

  • isa结构分析

    在我们iOS开发进行lldb调试的时候,经常会在控制台看到isa的存在,那么本文就来分析一下isa的结构。 在分析...

  • isa结构分析

    背景 书接上回alloc流程图分析中,在最后calloc分配空间,可得到空间的地址,那么calloc中系统是如何分...

  • ISA结构分析

    了解对象 Objective-C是一门面向对象编程语言。对象是什么,我们这篇文章讲的isa和对象又有什么样的关系呢...

  • isa结构分析

    在之前的文章OC对象的alloc过程中,我们探讨了OC对象初始化的主要过程,在第三步,主要是调用 initInst...

  • isa结构分析

    在对象调用alloc, 之后调用的最后一个方法是obj->initInstanceIsa, 它的作用是将isa指针...

网友评论

      本文标题:isa结构分析

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