美文网首页
OC对象的本质

OC对象的本质

作者: 英雄出少年 | 来源:发表于2019-04-30 14:35 被阅读0次
  • 平时编写的Objective-C代码,底层转换成C\C++代码,所以OC的面向对象都是基于C\C++的数据结构实现的


    OC底层转化过程.png
Objective-C的对象、类主要是基于C\C++的什么数据结构实现的?

结构体

将Objective-C代码转换为C\C++代码?
xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc  OC源文件  -o  输出的CPP文件
如果需要链接其他框架,使用-framework参数。比如-framework UIKit
查看内存数据

Debug -> Debug Workfllow -> View Memory (Shift + Command + M

示意图.png
常用LLDB指令
print、p:打印

po:打印对象

读取内存
memory read/数量格式字节数  内存地址
x/数量格式字节数  内存地址
x/3xw  0x10010


格式
x是16进制,f是浮点,d是10进制

字节大小
b:byte 1字节,h:half word 2字节
w:word 4字节,g:giant word 8字节


修改内存中的值
memory  write  内存地址  数值
memory  write  0x0000010  10

一个NSObject对象占用多少内存?

系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得

NSObject对象底层实现.png 内存分配.png

底层源码验证

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    
    /**  class_getInstanceSize 底层代码实现
     size_t class_getInstanceSize(Class cls)
     {
     if (!cls) return 0;
     return cls->alignedInstanceSize();
     }
     // Class's ivar size rounded up to a pointer-size boundary.
     uint32_t alignedInstanceSize() {
     return word_align(unalignedInstanceSize());
     }
     //alloc 底层源码分配内存实现
     size_t instanceSize(size_t extraBytes) {
     size_t size = alignedInstanceSize() + extraBytes;
     // CF requires all objects be at least 16 bytes.
     if (size < 16) size = 16;
     return size;
     }
     
     */
        NSObject *objc = [[NSObject alloc] init];
        // 获得NSObject实例对象的成员变量所占用的大小 ->  8
        NSLog(@"%zd",class_getInstanceSize([NSObject class]));
         // 获得obj指针所指向内存的大小 -> 16
        NSLog(@"%zd",malloc_size((__bridge const void*)objc));
        
    }
    return 0;
}

/**  内存中的表现
struct NSObject_IMPL {
    Class isa;
};

struct TGPerson_IMPL {
    struct NSObject_IMPL NSObject_IVARS;//8
    int _age;//4
    int _height;//4
    int _no;//4
}; // 计算结构体内存对齐:内存大小是最大成员变量的倍数,24
*/
@interface TGPerson : NSObject
{
    int _age;
    int _height;
    int _no;
}
@end

@implementation TGPerson

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TGPerson *p = [[TGPerson alloc] init];
        NSLog(@"%zd %zd",
              class_getInstanceSize([TGPerson class]), // 24
              malloc_size((__bridge const void *)(p))); // 32
        
    }
    return 0;
}
内存表现.png 底层分配内存函数.png 操作系统分配内存规则.png

OC对象的本质

  • instance对象(实例对象)
    instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
    实例对象.png

object1、object2是NSObject的instance对象(实例对象)
它们是不同的两个对象,分别占据着两块不同的内存

instance对象在内存中存储的信息包括

  • isa指针
  • 其他成员变量


    person对象.png
赋值.png p1对象.png p2对象.png
  • class对象(类对象)
类对象.png
它们是同一个对象。每个类在内存中有且只有一个class对象

class对象在内存中存储的信息主要包括

  • isa指针
  • superclass指针
  • 类的属性信息(@property)、类的对象方法信息(instance method)
  • 类的协议信息(protocol)、类的成员变量信息(ivar)
  • meta-class对象(元类对象)
    objectMetaClass是NSObject的meta-class对象(元类对象)
    meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括
    • isa指针
    • superclass指针
    • 类的类方法信息(class method)

判断是否是元类对象
Bool result = class_isMetaClass([NSObject class])

object_getClass
Class object_getClass(id obj)
{
  //如果是instance对象返回的是class  对象
  //如果是class对象返回的是meta-class对象
  //如果是meta-class对象,返回的是NSObject(基类)的meta-class对象
    if (obj) return obj->getIsa();
    else return Nil;
}

isa
isa指向.png
  • instance的isa指向class
    当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

  • class的isa指向meta-class
    当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

对象的isa指针指向哪里?

instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象

OC的类信息存放在哪里?

对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象

superclass(类对象内部指针)
superclass指针.png

当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

meta-class的superclass.png

当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

isa、superclass.png
instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class
class的superclass指向父类的class
如果没有父类,superclass指针为nil

meta-class的superclass指向父类的meta-class
基类的meta-class的superclass指向基类的class

instance调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类

class调用类方法的轨迹
isa找meta-class,方法不存在,就通过superclass找父类
&掩码.png 掩码宏.png

从64bit开始,isa需要进行一次位运算,才能计算出真实地址

@interface TGPerson : NSObject
@end
@implementation TGPerson
@end
struct tg_objc_class {
    Class isa;
    Class superclass;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
 // TGPerson实例对象的isa:0x001d8001000014c9      
  // TGPerson类对象的地址:0x00000001000014c8
        // isa & ISA_MASK:0x00000001000014c8 & 0x00007ffffffffff8
        TGPerson *person = [[TGPerson alloc] init];
        struct tg_objc_class *personClass = (__bridge struct tg_objc_class *)([TGPerson class]);
        
  struct tg_objc_class *studentClass = (__bridge struct tg_objc_class *)([TGStudent class]);
    return 0;
}
屏幕快照 2019-05-05 下午11.20.40.png

superclass不需要&掩码

屏幕快照 2019-05-05 下午11.15.38.png class内部结构.png

class、meta-class对象的本质结构都是struct objc_class

class内部结构底层源码.png
iOS设备CPU架构
  • 模拟器
    4s ~ 5: i386
    5s ~ 7Plus:x86_64

  • 真机设备
    armv6: iPhone、iPhone 2、iPhone 3G、iPod Touch(第一代)、iPod Touch(第二代)
    armv7: iPhone 3Gs、iPhone 4、iPhone 4s、iPad、iPad 2
    armv7s: iPhone 5、iPhone 5c (静态库只要支持了armv7,就可以在armv7s的架构上运行)
    arm64: iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3

相关文章

网友评论

      本文标题:OC对象的本质

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