1、class的底层结构探究
通过如下代码进行 class
的结构调试
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
NSLog(@"Person");
}
return 0;
}
// Person.h
@interface Person : NSObject {
NSString *subject;
}
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *hobby;
- (void)sayNB;
+ (void)say666;
@end
// Person.m
@implementation Person
- (void)sayNB {}
+ (void)say666 {}
@end
补充:
1、objc_class
继承自objc_object
2、p
是objc_class
对象,Person
对象为objc_object
结构体
3、id
为objc_object*
指针
4、class
是objc_object
的指针地址
1.1、objc_class
继承自 objc_object
struct objc_object {
private:
isa_t isa;
}
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits;
}
从类的结构中分析得知,前 8
个字节为 isa
, 后 8
个字节为 superclass
控制台操作:
x/4gx Person.class
Person
元类的内存结构
0x100008380: 0x00000001000083a8 0x000000010036e140
0x100008390: 0x000000010066c070 0x0002802800000003
po 0x00000001000083a8
第一个 8
个字节(isa
)打印结果
Person
po 0x000000010036e140
第二个 8
个字节(superclass
)打印结果
NSObject
1.2、cache_t
cache_t
的结构体如下
struct cache_t {
private:
explicit_atomic<uintptr_t> _bucketsAndMaybeMask; // 8
union {
struct {
explicit_atomic<mask_t> _maybeMask; // 4
#if __LP64__
uint16_t _flags; // 2
#endif
uint16_t _occupied; // 2
};
explicit_atomic<preopt_cache_t *> _originalPreoptCache; // 8
};
}
struct explicit_atomic : public std::atomic<T> {
}
explicit_atomic
为泛型结构,大小为泛型的类型
cache_t
结构体的大小为 16
个字节
1.3、class_data_bits_t
struct class_data_bits_t {
friend objc_class;
// Values are the FAST_ flags above.
uintptr_t bits;
public:
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
}
综上 class_data_bits_t
位于 objc_class
的第 36
个字节处
p/x 0x100008380+0x20
(long) $7 = 0x00000001000083a0
p (class_data_bits_t *)0x00000001000083a0
(class_data_bits_t *) $8 = 0x00000001000083a0
p $8->data()
查看 class_data_bits_t
里面的 data()
内容
(class_rw_t *) $10 = 0x000000010066c030
p *$10
查看 class_rw_t
的内容
(class_rw_t) $11 = {
flags = 2148007936
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned long> = {
Value = 4295000344
}
}
firstSubclass = nil
nextSiblingClass = 0x00007fff80103a88
}
1.4、以下是通过 class_rw_t
的源码来查找类的属 性内容
class_rw_t
部分源码
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t witness;
#if SUPPORT_INDEXED_ISA
uint16_t index;
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext;
Class firstSubclass;
Class nextSiblingClass;
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
}
}
}
p $11.properties()
查看 properties
属性
(const property_array_t) $12 = {
list_array_tt<property_t, property_list_t, RawPtr> = {
= {
list = {
ptr = 0x0000000100008260
}
arrayAndFlag = 4295000672
}
}
}
p $12.list
查看 list
里面的迭代器内容
(const RawPtr<property_list_t>) $13 = {
ptr = 0x0000000100008260
}
p $13.ptr
查看 ptr
地址
(property_list_t *const) $14 = 0x0000000100008260
p *$14
查看 ptr
的内部结构
(property_list_t) $15 = {
entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
p $15.get(0)
调用 get
方法获取属性值
(property_t) $16 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
1.5、属性
探究:属性列表存在于结构体
class_ro_t
中
x/4gx Person.class
查看 Person
的元类信息
0x100008408: 0x0000000100008430 0x000000010036e140
0x100008418: 0x0000000100662570 0x0002802800000003
p/x 0x100008408+0x20
查看 class_data_bits_t
结构体
(long) $1 = 0x0000000100008428
p (class_data_bits_t *)0x0000000100008428
(class_data_bits_t *) $2 = 0x0000000100008428
p $2->safe_ro()
(const class_ro_t *) $3 = 0x0000000100008188
查看源码 class_ro_t
结构体
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
union {
const uint8_t * ivarLayout;
Class nonMetaclass;
};
explicit_atomic<const char *> name;
// With ptrauth, this is signed if it points to a small list, but
// may be unsigned if it points to a big list.
void *baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
_objc_swiftMetadataInitializer __ptrauth_objc_method_list_imp _swiftMetadataInitializer_NEVER_USE[0];
}
p *$3
查看 class_ro_t
结构体
(const class_ro_t) $4 = {
flags = 0
instanceStart = 8
instanceSize = 32
reserved = 0
= {
ivarLayout = 0x0000000000000000
nonMetaclass = nil
}
name = {
std::__1::atomic<const char *> = "LGPerson" {
Value = 0x0000000100003f4d "LGPerson"
}
}
baseMethodList = 0x00000001000081d0
baseProtocols = nil
ivars = 0x0000000100008268
weakIvarLayout = 0x0000000000000000
baseProperties = 0x00000001000082d0
_swiftMetadataInitializer_NEVER_USE = {}
}
p $3->ivars
查看 Person
类的属性
(const ivar_list_t *const) $5 = 0x0000000100008268
p *$5
查看变量的具体信息
(const ivar_list_t) $6 = {
entsize_list_tt<ivar_t, ivar_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 32, count = 3)
}
p $6.get(0)
查看属性
(ivar_t) $7 = {
offset = 0x00000001000083a0
name = 0x0000000100003e11 "hobby"
type = 0x0000000100003f56 "@\"NSString\""
alignment_raw = 3
size = 8
}
2、内存平移
// main.m
@interface Person : NSObject
{
NSString *hobby;
NSObject *objc;
}
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, strong) NSString *name;
@property (atomic, strong) NSString *aname;
+ (void)test;
- (void)test;
@end
@implementation Person
+ (void)test {}
- (void)test {}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc]init];
p.name = @"KC";
p.nickName = @"老师";
p.aname = @"aNNN";
}
return 0;
}
以上是 main.m
的具体类结构
使用命令编译 main.m
文件
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
编译后的属性部分源码
static NSString * _I_Person_nickName(Person * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_nickName)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_Person_setNickName_(Person * self, SEL _cmd, NSString *nickName) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct Person, _nickName), (id)nickName, 0, 1); }
static NSString * _I_Person_name(Person * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_name)); }
static void _I_Person_setName_(Person * self, SEL _cmd, NSString *name) { (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_name)) = name; }
static NSString * _I_Person_aname(Person * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_aname)); }
static void _I_Person_setAname_(Person * self, SEL _cmd, NSString *aname) { (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_aname)) = aname; }
- 具有
copy
的属性,编译后的结果中执行objc_setProperty
方法
查看objc
源码
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
if (offset == 0) {
object_setClass(self, newValue);
return;
}
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:nil];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:nil];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
oldValue = *slot;
*slot = newValue;
slotlock.unlock();
}
objc_release(oldValue);
}
void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy)
{
bool copy = (shouldCopy && shouldCopy != MUTABLE_COPY);
bool mutableCopy = (shouldCopy == MUTABLE_COPY);
reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy);
}
void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset)
{
reallySetProperty(self, _cmd, newValue, offset, true, false, false);
}
void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset)
{
reallySetProperty(self, _cmd, newValue, offset, false, false, false);
}
void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset)
{
reallySetProperty(self, _cmd, newValue, offset, true, true, false);
}
void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset)
{
reallySetProperty(self, _cmd, newValue, offset, false, true, false);
}
最终调用 copyWithZone
方法
- 没有
copy
的属性,直接执行内存平移
比如 (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_name)) = name;