美文网首页
isa -初始化和指向浅析学习

isa -初始化和指向浅析学习

作者: 竹屋听雨 | 来源:发表于2019-12-22 11:55 被阅读0次

isa: 对象的第一个属性必然是isa ,来源是继承NSObject

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

---初始化isa

inline void 
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{ 
    assert(!isTaggedPointer()); 
    
    if (!nonpointer) {
        isa.cls = cls;
    } else {
        assert(!DisableNonpointerIsa);
        assert(!cls->instancesRequireRawIsa());

        isa_t newisa(0);

#if SUPPORT_INDEXED_ISA
        assert(cls->classArrayIndex() > 0);
        newisa.bits = ISA_INDEX_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.indexcls = (uintptr_t)cls->classArrayIndex();
#else
        newisa.bits = ISA_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.shiftcls = (uintptr_t)cls >> 3;
#endif

        // This write must be performed in a single store in some cases
        // (for example when realizing a class because other threads
        // may simultaneously try to use the class).
        // fixme use atomics here to guarantee single-store and to
        // guarantee memory order w.r.t. the class index table
        // ...but not too atomic because we don't want to hurt instantiation
        isa = newisa;
    }
}

isa < ----- > cls

 LGPerson *object = [LGPerson alloc];
打印当前类的结构
 x/4gx object
0x101a2c940: 0x001d800100001131 0x0000000000000000
0x101a2c950: 0x0000000101a2ca20 0x0000000101a2cc60
打印当前二进制isa   
Mark:「p/t2进制 p/x 16进制  p/o 8进制 p/d10进制打印」
 p/t 0x001d800100001131
(long) $1 = 0b0000000000011101100000000000000100000000000000000001000100110001
打印当前类class
 p/x LGPerson.class
(Class) $2 = 0x0000000100001130 LGPerson
打印当前类机构二进制
《《《newisa.shiftcls = (uintptr_t)cls >> 3;》》》
p/t (uintptr_t)LGPerson.class
(uintptr_t) $3 = 0b0000000000000000000000000000000100000000000000000001000100110000
右移动三位
 p/t $3>>3
(uintptr_t) $4 = 0b0000000000000000000000000000000000100000000000000000001000100110
isa 指针右移动三位
 p/t $1>>3
(long) $5 = 0b0000000000000011101100000000000000100000000000000000001000100110
然后再左移动
 p/t $5<<17
(long) $6 = 0b0110000000000000010000000000000000000100010011000000000000000000
右移动17位
 p/t $6>>17
(long) $7 = 0b0000000000000000001100000000000000100000000000000000001000100110

$5 --$7 比较发现后面是一样的

我们还可以通过这个方法去查看:
当前对象 通过这个方法拿到一个类。他是怎样关联的呢?
object_getClass(object);

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}
     
inline Class 
objc_object::getIsa() 
{
Mark:---------👇
    if (!isTaggedPointer()) return ISA();

    uintptr_t ptr = (uintptr_t)this;
    if (isExtTaggedPointer()) {
        uintptr_t slot = 
            (ptr >> _OBJC_TAG_EXT_SLOT_SHIFT) & _OBJC_TAG_EXT_SLOT_MASK;
        return objc_tag_ext_classes[slot];
    } else {
        uintptr_t slot = 
            (ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_SLOT_MASK;
        return objc_tag_classes[slot];
    }
}
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
Mark:---------👇 ISA_MASK:相当于一个掩码
    return (Class)(isa.bits & ISA_MASK);
#endif
}   

 p/x LGPerson.class
(Class) $1 = 0x0000000100001130 LGPerson
 p/x  0x001d800100001131 & 0x00007ffffffffff8
(long) $2 = 0x0000000100001130
po 一下当前的指针 就会得到当前的类
 po 0x0000000100001130
LGPerson

isa 的结构在arm64 和x86结构下是不一样的


# 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;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif

类在内存里面只有一份: 对象是可以创建多个;

//MARK: - 分析类对象内存存在个数
void lgTestClassNum(){
    Class class1 = [LGPerson class];
    Class class2 = [LGPerson alloc].class;
    Class class3 = object_getClass([LGPerson alloc]);
    Class class4 = [LGPerson alloc].class;
    NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
}
2019-12-22 15:12:13.588387+0800 001-对象isa[32132:1886315] 
0x100002420-
0x100002420-
0x100002420-
0x100002420

类-元类

LGPerson *object = [LGPerson alloc];  
我们x一下内存结构
x/4gx object.class
0x100001130: 0x001d800100001109 0x0000000100aff140
0x100001140: 0x0000000100fa2090 0x0000000200000003
然后打印一下当前指针的对象:
po 0x100001130
LGPerson  
居然又指向了LGPerson 这个类??!!
A->b->A
实际上这个是meta class 元类 
Mark:
类:我们在创建的一个类的时候 向系统申请开辟内存空间,系统会根据这个来给我们实例化出来。在系统中只存在一份。
元类:系统编译出来的,来源于编译器,根据创建的类,来生成元类,方便后期的存储使用。
 对象的isa --> 类 isa --> 元类 -->根元类
屏幕快照 2019-12-22 下午3.33.02.png isa流程图.png
union 联合体 
isa_t 是一个联合体,Class cls 与 uintptr_t bits 是互斥的,在初始化isa 的时候,如果是nopointisa 就对当前的bit 进行一系列的操作。如果不是nopointisa 就直接关联当前的cls 就好了。只需要表达类的信息,类的指向就行了。
截屏2019-12-18下午6.19.24.png

相关文章

  • isa -初始化和指向浅析学习

    isa: 对象的第一个属性必然是isa ,来源是继承NSObject ---初始化isa isa < -----...

  • 第一天重点图

    一、alloc 二、内存对齐 三、isa的初始化 & 指向分析

  • isa的初始化和指向

    struct objc_object { Class_Nonnull isa OBJC_ISA_AVAILAB...

  • iOS-isa的初始化和指向

    isa的初始化和指向 什么是isa isa是所有类结构体的第一个成员变量,被注释类说明是继承于objc_objec...

  • isa的初始化和指向分析

    isa的初始化 isa的初始化流程代码 问题解释:为什么赋值了cls之后就不赋值bits了? 原因是:isa是一个...

  • ISA指向、类结构

    ISA指向、类结构 1.ISA指向 上次在对象本质和ISA指针[https://www.jianshu.com/p...

  • isa初始化&指向分析

    探索对象与类如何绑定在一起 在objc4的源码中,通过研究alloc的流程就可看到下面的代码 上面的代码我们可以看...

  • isa的流程和类的继承

    isa的指向流程: NSObejct:实例对象的isa指向 元类,元类的isa指向根元类,根元类的isa指向自己 ...

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

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

  • isa指针

    对象的isa指针指向哪里?instance对象的isa指向class对象class对象的isa指向meta-cla...

网友评论

      本文标题:isa -初始化和指向浅析学习

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