oc 对象的本质与isa

什么是对象

Clang

Clang是C语言、C++、Objective-c语言的轻量编译器。源代码发布于BSD协议下。
Clang将支持lambad表达式,返回类型的简单处理以及更好的处理constexpr关键字。
Clang有Apple主导编写,基于LLVM的C/C++/Objective-c编译器

准备阶段

main.m 编译成 main.cpp 文件

clang -rewrite-objc main.m -o main.cpp
复制代码

如果出现

In file included from ViewController.m:9:
./ViewController.h:9:9: fatal error: 'UIKit/UIKit.h' file not found
#import <UIKit/UIKit.h>
        ^~~~~~~~~~~~~~~
1 error generated.
复制代码

解决办法

clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /
Applications/Xcode.app/Contents/Developer/Platforms/
iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
复制代码

xcrun编译

//模拟器
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o 
main-arm64.cpp

//真机
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o 
main-arm64.cpp
复制代码

分析阶段

main.m 声明一个 LGPerson

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface LGPerson : NSObject
@property (nonatomic, strong) NSString *Name;
@end

@implementation LGPerson

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

复制代码

在生成的main.cpp文件中找到LGPerson对应的地方

struct LGPerson_IMPL {
	struct NSObject_IMPL NSObject_IVARS;
	NSString *_Name;
};
复制代码
  1. 对比 .m 文件可以得出结论对象在底层的本质是结构体

然后在文件中查找 struct NSObject_IMPL 结构体发现

struct NSObject_IMPL {
	Class isa;
};
复制代码
  1. 得出结论 NSObject_IVARS是成员变量isa

  2. LGPerson是继承 NSObject,在cpp文件中是 objc_object 类型,所以 NSObject 对象在底层的类型是 objc_object

typedef struct objc_object NSObject;
复制代码
  1. 查找浏览cpp文件还发现,我们通常声明一个类时使用的 Class 的类型是 objc_class *,是一个结构体指针
typedef struct objc_class *Class;
复制代码
  1. id 的类型是 objc_object *,所以可以定义任何类型的变量
typedef struct objc_object *id;
复制代码
  1. getter/setter 隐藏参数:在.cpp文件中查找 LGPersonget/set方法
//getter
static NSString * _I_LGPerson_Name(LGPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_Name)); }
//setter
static void _I_LGPerson_setName_(LGPerson * self, SEL _cmd, NSString *Name) { (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_Name)) = Name; }
复制代码

结构体 联合体 位域

案例一

#import <Foundation/Foundation.h>

struct LGPerson {
    bool left;
    bool right;
    bool front;
    bool back;
};

struct LGPersonEx {
    bool left: 1;
    bool right: 1;
    bool front: 1;
    bool back: 1;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        struct LGPerson p1;
        NSLog(@"-%lu-",sizeof(p1));
        
        struct LGPersonEx p2;
        NSLog(@"-%lu-",sizeof(p2));
    }
    return 0;
}
复制代码

打印sizeof结果为:p1占用4字节空间, p2占用1字节空间

案例二

struct LGPerson {
    NSString *name;
    int age;
};

union LGPersonEx {
    NSString *name;
    int age;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        struct LGPerson p1;
        p1.name = @"swagger";
        p1.age  = 18;
        NSLog(@"-%lu-",sizeof(p1));
        
        union LGPersonEx p2;
        p2.name = @"swagger";
        p2.age  = 18;
        NSLog(@"-%lu-",sizeof(p2));
    }
    return 0;
}
复制代码

在p1和p2赋值的过程中分别打断点,.name = @"swagger"; .age = 18;

(lldb) p p1
(LGPerson) $0 = (name = 0x0000000000000000, age = 0)
(lldb) p p1
(LGPerson) $1 = (name = @"swagger", age = 0)
(lldb) p p1
(LGPerson) $2 = (name = @"swagger", age = 18)

(lldb) p p2
(LGPersonEx) $0 = (name = 0x0000000000000000, age = 0)
(lldb) p p2
(LGPersonEx) $1 = (name = "swagger", age = 16284)
(lldb) p p2
(LGPersonEx) $2 = (name = "", age = 18)
(lldb) 

复制代码

结论:

通过案例一,结构体内声明了4个bool类型,占用4字节内存,对结构体内声明的4个bool类型进行指定位域,指定每一个bool类型的成员变量使用1bit的内存空间,那么4个bool类型最终占用4bit空间,即0.5字节的空间,最终占用了1字节内存,为对象指定位域是内存优化的方式

通过案例二,也就是struct与union的区别,struct内成员变量的存储互不影响,union内的对象存储是互斥的
结构体(struct)中所有的变量是共存的,优点是可以存储所有的对象的值,比较全面。缺点是struct内存空间分配是粗放的,不管是否被使用,全部分配
联合体(union)中所有的变量是互斥的,优点是内存使用更加精细灵活,也节省了内存空间,缺点就是不够包容

nonpointerIsa初探

isa指针存了什么

通过宏定义ISA_BITFIELD找到了isa指针内都存放了什么, 分为两种模式

  • arm64
define ISA_MASK        0x0000000ffffffff8ULL
#     define ISA_MAGIC_MASK  0x000003f000000001ULL
#     define ISA_MAGIC_VALUE 0x000001a000000001ULL
#     define ISA_HAS_CXX_DTOR_BIT 1
#     define ISA_BITFIELD                                                      \
        uintptr_t nonpointer        : 1;       //是否为纯指针                                \
        uintptr_t has_assoc         : 1;       //关联对象                                \
        uintptr_t has_cxx_dtor      : 1;       //C++的析构函数                               \
        uintptr_t shiftcls          : 33; /     *MACH_VM_MAX_ADDRESS 0x1000000000*/ \           //类的指针地址
        uintptr_t magic             : 6;                                       \
        uintptr_t weakly_referenced : 1;        //弱引用                             \
        uintptr_t unused            : 1;                                       \
        uintptr_t has_sidetable_rc  : 1;        //散列表                               \
        uintptr_t extra_rc          : 19        //引用计数
#     define RC_ONE   (1ULL<<45)
#     define RC_HALF  (1ULL<<18)
复制代码
  • x86_64
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_HAS_CXX_DTOR_BIT 1
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;       //是否为纯指针                                    \
      uintptr_t has_assoc         : 1;       //关联对象                                  \
      uintptr_t has_cxx_dtor      : 1;       //C++的析构函数                                \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \    //类的指着地址
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;      //弱引用                                  \
      uintptr_t unused            : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;       //散列表                                  \
      uintptr_t extra_rc          : 8       //引用计数
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)
复制代码

图形分析

isa1.jpg

isa2.jpg

isa3.jpg

isa4.jpg

明月别枝惊鹊 清风半夜鸣蝉

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享