前言
关于
alloc已经探索完了 接下来我们来看一下isa分析到元类
一.isa走位图和继承链
一.lldb调试
先搞一波运行起来demo
LGPerson *test = [LGPerson alloc];
断点这里 NSLog(@"%@",test);
复制代码
1.lldb 终端输入如下命令得到实例对象地址
po test
<LGPerson: 0x10500de60> 得到实例对象内存地址
复制代码
2.打印内存
x/4gx 0x10500de60
0x10500de60(内存地址): 0x011d800100008365(如何能证明这个是isa) 0x0000000000000000
0x10500de70: 0x0000000000000000 0x0000000000000000
复制代码
3.得到类isa指向的地址
p/x 0x011d800100008365 & 0x00007ffffffffff8
(unsigned long long) $2 = 0x0000000100008360 (获取类的内存地址)
复制代码
4.打印类名称
po 0x0000000100008360
LGPerson(得到类名称)
复制代码
到此我们可以探索到实例对象的
isa->(LGPerson:0x0000000100008360)类 那么类对象的isa指向哪里呢?我们继续走你
5.打印类的内存
x/4gx 0x0000000100008360
0x100008360: 0x0000000100008338(isa) 0x00007fff88bdfcc8
0x100008370: 0x0000000100641640 0x0002802c00000003
复制代码
6.得到类isa指向的地址
p/x 0x0000000100008338 & 0x00007ffffffffff8
$8 = 0x0000000100008338(获取类的内存地址)
复制代码
7.打印类名称
po 0x0000000100008338
LGPerson(得到类名称)
复制代码
到此我们可以探索到
(LGPerson:0x0000000100008360)的isa->(LGPerson:0x0000000100008338(这是什么东东))
8.运行另外一个demo
Class class1 = [LGPerson class];
Class class2 = [LGPerson alloc].class;
Class class3 = object_getClass([LGPerson alloc]);
Class class4 = [LGPerson alloc].class;
NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
打印结果地址: 0x100008360-
0x100008360-
0x100008360-
0x100008360
和 LGPerson:0x0000000100008360 对的上
复制代码
9.看一下mach-o文件 LGPerson:0x0000000100008338 应该是元类

到此我们可以探索到
(LGPerson:0x0000000100008338)的isa又指向哪里呢 继续走你
10.打印元类的内存
x/4gx 0x0000000100008338
0x100008338: 0x00007fff88bdfca0 (isa)0x00007fff88bdfca0
0x100008348: 0x00000001006419d0 0x0002e03500000003
复制代码
11.得到元类isa指向的地址
p/x 0x00007fff88bdfca0 & 0x00007ffffffffff8ULL
(unsigned long long) $10 = 0x00007fff88bdfca0(获取类的内存地址)
复制代码
12.打印类名称
po 0x00007fff88bdfca0
NSObject
复制代码
到此我们可以探索到(LGPerson:0x0000000100008338)的isa 指向根元类(NSObject) 那么根元类的isa又指向哪里呢
13.打印根元类的内存
x/4gx 0x00007fff88bdfca0
0x7fff88bdfca0: 0x00007fff88bdfca0 0x00007fff88bdfcc8
0x7fff88bdfcb0: 0x0000000100641b10 0x0003e03100000007
复制代码
14.得到根元类isa指向的地址
p/x 0x00007fff88bdfca0 & 0x00007ffffffffff8
(unsigned long long) $12 = 0x00007fff88bdfca0(获取类的内存地址)
复制代码
15.打印类名称
po 0x00007fff88bdfca0
NSObject
复制代码
到此我们可以探索到根元类
(NSObject)的isa指向了自己
总结:对象
isa-> 类(LGPerson:0x0000000100008360) isa-> 元类(LGPerson:0x0000000100008338) isa-> 根元类(NSObject) isa-> 根元类
16.我们直接打印NSObject.class
p/x NSObject.class
(Class) $14 = 0x00007fff88bdfcc8 NSObject
打印类的内存
x/4gx 0x00007fff88bdfcc8
0x7fff88bdfcc8: 0x00007fff88bdfca0 0x0000000000000000
0x7fff88bdfcd8: 0x0000000105007bd0 0x0002801000000003
打印类的地址
p/x 0x00007fff88bdfca0 & 0x00007ffffffffff8
(long) $15 = 0x00007fff88bdfca0
打印类的名称
po 0x00007fff88bdfca0
NSObject
复制代码
总结:根类
isa-> 根元类isa->根元类
二.代码调试isa走向
1.我们创建的NSObject实例对象演示:

2.我们创建LGPerson实例对象演示:

3.因为LGTeacher继承于LGPerson,LGTeacher实例对象演示:

下面我们探索一下继承的
isa是怎么样指向的 直接上代码
三.代码调试isa继承走向
一.类继承的isa指向
1.我们先看一下 NSObject.class的isa指向

2.我们看一下 LGPerson.class的isa指向

3.我们看一下 LGTeacher.class的isa指向

4.我们看一下 LGXiaowen.class的isa指向

二.元类继承的isa指向
1.我们先看一下 NSObject.class元类的isa指向

2.我们看一下 LGPerson.class元类的isa指向

3.我们看一下 LGTeacher.class元类的isa指向

4.我们看一下 LGXiaowen.class元类的isa指向

结合上面分析得到如下结论如下图

二.源码分析类的结构

三.指针和内存平移
// 数组指针
int c[4] = {1,2,3,4};
int *d = c;
NSLog(@"%p - %p - %p",&c,&c[0],&c[1]);
NSLog(@"%p - %p - %p",d,d+1,d+2);
for (int i = 0; i<4; i++) {
int value = *(d+i);
NSLog(@"%d",value);
}
打印得出:002-内存偏移[38980:1658739] 0x7ffeefbff3c0 - 0x7ffeefbff3c0 - 0x7ffeefbff3c4
2021-06-20 13:41:36.896925+0800 002-内存偏移[38980:1658739] 0x7ffeefbff3c0 - 0x7ffeefbff3c4 - 0x7ffeefbff3c8
2021-06-20 13:41:37.939247+0800 002-内存偏移[38980:1658739] 1
2021-06-20 13:42:19.343718+0800 002-内存偏移[38980:1658739] 2
2021-06-20 13:42:19.343888+0800 002-内存偏移[38980:1658739] 3
2021-06-20 13:42:19.343959+0800 002-内存偏移[38980:1658739] 4
复制代码
根据指针内存的平移获取数组相应的取值 这样我们就可以根据类的首地址进行平台获取里面成员变量的值
四.类的结构内存计算

x/4gx LGPerson.class
0x100008380: 0x00000001000083a8 0x000000010036a140
0x100008390: 0x0000000101052a80 0x0002802800000003
0x00000001000083a8:对应Class ISA
0x000000010036a140:对应Class superclass
0x0000000101052a80:对应cache_t cache
0x0002802800000003:class_data_bits bits
复制代码
想要获取到bits 就的通过首地址平移这些长度ISA(8字节)->superclass(8字节)->cache(多少呢)

cache = 8+8 = 16 所以平移到bits需要移动32

五.lldb分析类的结构
1.在class_rw_t里面查找LGPerson的成员变量
(lldb) x/4gx LGPerson.class
0x100008380: 0x00000001000083a8 0x000000010036a140
0x100008390: 0x0000000100764050 0x0002802800000003
(lldb) p (class_data_bits_t *) 0x1000083a0 //获取class_data_bits_t +32
(class_data_bits_t *) $1 = 0x00000001000083a0
(lldb) p $1->data() //获取 class_rw_t
(class_rw_t *) $2 = 0x0000000100764010
(lldb) p * $2 //查看 class_rw_t
(class_rw_t) $3 = {
flags = 2148007936
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned long> = {
Value = 4295000344
}
}
firstSubclass = nil
nextSiblingClass = NSUUID
}
//获取属性
(lldb) p $2.properties() //查看 class_rw_t.properties()
(const property_array_t) $4 = {
list_array_tt<property_t, property_list_t, RawPtr> = {
= {
`list` = {
ptr = 0x0000000100008260
}
arrayAndFlag = 4295000672
}
}
}
Fix-it applied, fixed expression was:
$2->properties()
(lldb) p $4.list //上面返回的
(const RawPtr<property_list_t>) $5 = {
`ptr` = 0x0000000100008260
}
(lldb) p $5.ptr
(property_list_t *const) $6 = 0x0000000100008260
(lldb) p *$6
(property_list_t) $7 = {
`entsize_list_tt`<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $7.get(0)
(property_t) $8 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
p $7.get(1)
(property_t) $9 = (name = "hobby", attributes = "T@\"NSString\",C,N,V_hobby")
获取对象实例方法
p $2.methods() //查看 class_rw_t.methods()
(const method_array_t) $10 = {
list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {
= {
list = {
ptr = 0x0000000100008160
}
arrayAndFlag = 4295000416
}
}
}
Fix-it applied, fixed expression was:
$2->methods()
(lldb) p $10.list
(const method_list_t_authed_ptr<method_list_t>) $11 = {
ptr = 0x0000000100008160
}
(lldb) p $11.ptr
(method_list_t *const) $12 = 0x0000000100008160
(lldb) p *$12
(method_list_t) $13 = {
entsize_list_tt<method_t, method_list_t, 4294901763, method_t::pointer_modifier> = (entsizeAndFlags = 27, count = 6)
}
(lldb) p $13.get(0).big().name
(SEL) $14 = "hobby"
(lldb) p $13.get(1).big().name
(SEL) $15 = "sayNB"
(lldb) p $13.get(2).big().name
(SEL) $16 = "setHobby:"
(lldb) p $13.get(3).big().name
(SEL) $17 = "init"
(lldb) p $13.get(4).big().name
(SEL) $18 = "name"
(lldb) p $13.get(5).big().name
(SEL) $19 = "setName:"
(lldb) p $13.get(6).big().name
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)