iOS底层问题

2020-03-22  本文已影响0人  Leevi_w

1.介绍下runtime的内存模型(isa、对象、类、metaclass、结构体的存储信息等

对象
struct objc_object{
         Class isa OBJC_ISA_AVAILABILITY; 
    };

isa

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits; // uintptr_t本质是 unsigned long  ,在处理器中占用8个字节,正好是64位的二级制
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

类 metaclass

struct objc_class{
    Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
     Class super_class                        OBJC2_UNAVAILABLE;  // 父类
     const char *name                         OBJC2_UNAVAILABLE;  // 类名
     long version                             OBJC2_UNAVAILABLE;  // 类的版本信息,默认为0
     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;

metaclass

2.为什么要设计metaclass?

Why is MetaClass in Objective-C? - 简书

大概意思就是类也是一个对象,指针指向父类,最终指向元类,存放类方法

3.class_copyIvarList & class_copyPropertyList区别

首先先看IvarProperty 是什么,class_copyIvarListclass_copyPropertyList区别 在runtime中的实现


struct property_t {
    const char *name; //属性名称
    const char *attributes; // 属性
};

struct ivar_t {
#if __x86_64__
    // *offset was originally 64-bit on some x86_64 platforms.
    // We read and write only 32 bits of it.
    // Some metadata provides all 64 bits. This is harmless for unsigned 
    // little-endian values.
    // Some code uses all 64 bits. class_addIvar() over-allocates the 
    // offset for their benefit.
#endif
    int32_t *offset; // 偏移量,只读写32位
    const char *name; // 变量名称
    const char *type; // 类型
    // alignment is sometimes -1; use alignment() instead
    uint32_t alignment_raw;  // 编译时期对齐
    uint32_t size; // 变量内存大小

    uint32_t alignment() const {
        if (alignment_raw == ~(uint32_t)0) return 1U << WORD_SHIFT;
        return 1 << alignment_raw;
    } // 对齐方法
};


/***********************************************************************
* class_copyIvarList
* fixme
* Locking: read-locks runtimeLock
**********************************************************************/
Ivar *
class_copyIvarList(Class cls, unsigned int *outCount)
{
    const ivar_list_t *ivars;
    Ivar *result = nil;
    unsigned int count = 0;

    if (!cls) {
        if (outCount) *outCount = 0;
        return nil;
    }

    mutex_locker_t lock(runtimeLock);

    ASSERT(cls->isRealized());
    
    if ((ivars = cls->data()->ro->ivars)  &&  ivars->count) {
        result = (Ivar *)malloc((ivars->count+1) * sizeof(Ivar));
        
        for (auto& ivar : *ivars) {
            if (!ivar.offset) continue;  // anonymous bitfield
            result[count++] = &ivar;
        }
        result[count] = nil;
    }
    
    if (outCount) *outCount = count;
    return result;
}

/***********************************************************************
* class_copyPropertyList. Returns a heap block containing the 
* properties declared in the class, or nil if the class 
* declares no properties. Caller must free the block.
* Does not copy any superclass's properties.
* Locking: read-locks runtimeLock
**********************************************************************/
objc_property_t *
class_copyPropertyList(Class cls, unsigned int *outCount)
{
    if (!cls) {
        if (outCount) *outCount = 0;
        return nil;
    }

    mutex_locker_t lock(runtimeLock);

    checkIsKnownClass(cls);
    ASSERT(cls->isRealized());
    
    auto rw = cls->data();

    property_t **result = nil;
    unsigned int count = rw->properties.count();
    if (count > 0) {
        result = (property_t **)malloc((count + 1) * sizeof(property_t *));

        count = 0;
        for (auto& prop : rw->properties) {
            result[count++] = &prop;
        }
        result[count] = nil;
    }

    if (outCount) *outCount = count;
    return (objc_property_t *)result;
}

4.class_rw_t 和 class_ro_t 的区别

struct class_rw_t {
  // Be warned that Symbolication knows the layout of this structure.
  uint32_t flags;
  uint32_t version;

  const class_ro_t *ro;

  method_array_t methods;
  property_array_t properties;
  protocol_array_t protocols;

  Class firstSubclass;
  Class nextSiblingClass;

  char *demangledName;

#if SUPPORT_INDEXED_ISA
  uint32_t index;
#endif

  void setFlags(uint32_t set) 
  {
      OSAtomicOr32Barrier(set, &flags);
  }

  void clearFlags(uint32_t clear) 
  {
      OSAtomicXor32Barrier(clear, &flags);
  }

  // set and clear must not overlap
  void changeFlags(uint32_t set, uint32_t clear) 
  {
      assert((set & clear) == 0);

      uint32_t oldf, newf;
      do {
          oldf = flags;
          newf = (oldf | set) & ~clear;
      } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
  }
};

struct class_ro_t {
  uint32_t flags;
  uint32_t instanceStart;
  uint32_t instanceSize;
#ifdef __LP64__
  uint32_t reserved;
#endif

  const uint8_t * ivarLayout;
  
  const char * name;
  method_list_t * baseMethodList;
  protocol_list_t * baseProtocols;
  const ivar_list_t * ivars;

  const uint8_t * weakIvarLayout;
  property_list_t *baseProperties;

  // This field exists only when RO_HAS_SWIFT_INITIALIZER is set.
  _objc_swiftMetadataInitializer __ptrauth_objc_method_list_imp _swiftMetadataInitializer_NEVER_USE[0];

  _objc_swiftMetadataInitializer swiftMetadataInitializer() const {
      if (flags & RO_HAS_SWIFT_INITIALIZER) {
          return _swiftMetadataInitializer_NEVER_USE[0];
      } else {
          return nil;
      }
  }

  method_list_t *baseMethods() const {
      return baseMethodList;
  }

  class_ro_t *duplicate() const {
      if (flags & RO_HAS_SWIFT_INITIALIZER) {
          size_t size = sizeof(*this) + sizeof(_swiftMetadataInitializer_NEVER_USE[0]);
          class_ro_t *ro = (class_ro_t *)memdup(this, size);
          ro->_swiftMetadataInitializer_NEVER_USE[0] = this->_swiftMetadataInitializer_NEVER_USE[0];
          return ro;
      } else {
          size_t size = sizeof(*this);
          class_ro_t *ro = (class_ro_t *)memdup(this, size);
          return ro;
      }
  }
};

5.loadinitialize方法的区别是什么,在继承关系中他们有什么区别?

6.IMPSEL, Method 的区别


/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

/// A pointer to the function of a method implementation. 
typedef void (*IMP)(void /* id, SEL, ... */ ); 

  struct method_t {
  SEL name;
  const char *types;
  MethodListIMP imp;

  struct SortBySELAddress :
      public std::binary_function<const method_t&,
                                  const method_t&, bool>
  {
      bool operator() (const method_t& lhs,
                       const method_t& rhs)
      { return lhs.name < rhs.name; }
  };
};

7.category&extention区别,能给NSObject添加extention嘛,结果如何?

8.在方法调用的时候,方法查询,动态解析,消息转发之前做了什么?

9.category 如何被加载的,两个cateforyload方法的加载顺序,两个category的同名方法的加载顺序

10.说说消息转发机制的优劣,以及其他语言的消息机制优劣对比
11.runtime的加载过程

void _objc_init(void)
{
   static bool initialized = false;
   if (initialized) return;
   initialized = true;
   
   // fixme defer initialization until an objc-using image is found?
   environ_init();
   tls_init();
   static_init();
   lock_init();
   exception_init();

   _dyld_objc_notify_register(&map_images, load_images, unmap_image);
}

weak的实现原理?SideTale的结构?

汇编语言基础

汇编语言入门教程 - 阮一峰的网络日志

上一篇 下一篇

猜你喜欢

热点阅读