(一)OC對象在底層中的布局
我們平時編寫的Objective-C
代碼递礼,在底層都是使用C/C++
實現(xiàn)。
即Objective-C
-> C/C++
-> 匯編語言
-> 機器語言
脾还。
我們定義個NSObject
對象
NSObject *object = [[NSObject alloc] init];
使用終端命令將OC
代碼轉(zhuǎn)換成iOS能支持的C/C++
代碼恢暖;
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 'OC源文件' -o '輸出的CPP文件'
通過閱讀轉(zhuǎn)換后的.cpp
文件浩峡,可以找到一個名為 NSObject_IMPL
的結(jié)構(gòu)體剩晴。分析結(jié)構(gòu)體名字實際含義是 NSObject Implementation
struct NSObject_IMPL {
Class isa;
};
因此我們可以知道OC對象在底層的布局是一個結(jié)構(gòu)體
。
(二)對象在內(nèi)存中的占用大小
引入<objc/runtime.h>
珍坊, 使用 class_getInstanceSize
方法可獲取NSObject
實例對象的 成員變量
所占用的大小牺勾,可以觀察到返回 8 個字節(jié)
class_getInstanceSize([NSObject class])
引入<malloc/malloc.h>
, 使用malloc_size
方法獲取指針所指向的內(nèi)存大小
阵漏,可以觀察到返回16
個字節(jié)驻民。
malloc_size((__bridge const void *)(object));
通過閱讀Objc源碼 可得知在alloc
一個對象時,CoreFunction
框架硬性規(guī)定分配內(nèi)存空間不小于16
個字節(jié)
總結(jié):
系統(tǒng)分配了
16
個字節(jié)給NSObject
對象(通過malloc_size
函數(shù)獲得),但NSObjec
t對象內(nèi)部只使用了8
個字節(jié)的空間(64bit環(huán)境下履怯,可以通過class_getInstanceSize
函數(shù)獲得)
(三)通過XCode工具分析內(nèi)存
首先打印NSObject
對象地址回还,通過工具ViewMemory
查看。
可觀察到前16
個字節(jié)中叹洲,只有8
個字節(jié)存在數(shù)據(jù)(存放isa
指針)
(四)自定義類內(nèi)存分析
定義Student
類柠硕,初始化。通過重復之前步驟,可觀察到底層實現(xiàn)蝗柔。
struct Student_IMPL {
Class isa;
int _no;
int _age;
};
@interface Student : NSObject
{
@public
int _no;
int _age;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu->_no = 4;
stu->_age = 5;
NSLog(@"%zd", class_getInstanceSize([Student class]));
NSLog(@"%zd", malloc_size((__bridge const void *)stu));
}
return 0;
}
通過使用class_getInstanceSize
與malloc_size
方法可觀察到占用16
個字節(jié)存儲空間闻葵。
使用
ViewMemory
查看前8
個字節(jié)存放isa
,_no
與_age
分別占用4
個字節(jié)癣丧。
我們也可以使用LLDB
指令打印相關地址信息
槽畔,并且可使用memory write
指令直接修改內(nèi)存中的數(shù)據(jù)
可以觀察到將
_no
中的值修改為了8
。
(五)繼承類的內(nèi)存占用分析
@interface Person : NSObject
{
@public
int _age;
}
@end
@implementation Person
@end
@interface Student : Person
{
int _no;
}
@end
@implementation Student
@end
分析:Person
類中isa
指針占用8
個字節(jié)胁编,_age
占用4
個字節(jié)厢钧。通過CoreFunction
框架硬性規(guī)定分配內(nèi)存空間不小于16個字節(jié)
。得知共占用16
個字節(jié)嬉橙。
但是
即使無此硬性規(guī)定早直,通過內(nèi)存對齊
規(guī)則:結(jié)構(gòu)體的最終大小,必須是最大成員的倍數(shù)市框。
霞扬。
Student
類占用16
個字節(jié)。isa
占用8
個字節(jié)拾给,_age
占用4
個字節(jié)祥得,剩余4
個字節(jié)兔沃,被_no
占用蒋得。