在上一篇博客里面iOS底层探索之类的结构(上):ISA已经大致的,了解了类的结构

类的结构

struct objc_class : objc_object {objc_class(const objc_class&) = delete;objc_class(objc_class&&) = delete;void operator=(const objc_class&) = delete;void operator=(objc_class&&) = delete;// Class ISA;Class superclass;cache_t cache;             // formerly cache pointer and vtableclass_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

class_data_bits

我们主要探究是class_data_bits_t bits,在bits里面有我们关心的类的信息。
那么我们怎么拿呢?先看看下面这个JPPerson

@interface JPPerson : NSObject
{int age;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;- (void)sayHello;
+ (void)sayNB;
@end
@implementation JPPerson- (instancetype)init{if (self = [super init]) {self.name = @"reno";}return self;
}
- (void)sayHello{}
+ (void)sayNB{}
@end

使用lldb调试 x/4gx 命令打印了JPPerson这个类的内存信息

第一个是isa;第二个是superclasspo 出来是NSObjectJPPerson 是继承NSObject的;那么以此类推,第三个是cache,第四个是bits

bits

我们要了解bits里面的data信息,该怎么拿呢?光知道一个地址也不行啊?那么我们既然知道了isa(首地址),是不是就可以通过指针偏移内存偏移拿到呢?那么要偏移多少个呢?

要想拿到bits,指针在内存中必须要平移指向bits,我知道isa是8个字节长度,superclass也是8个字节长度,那么cache_t呢?看看内部结构分析下

cache_t


分析得到cache_t是16,那么加isasuperclass一共就是32个字节的长度。

(lldb) x/4gx JPPerson.class
0x100008358: 0x0000000100008380 0x000000010036a140
0x100008368: 0x00000001003623c0 0x0000802800000000
(lldb) p/x 0x100008358+0x20
(long) $1 = 0x0000000100008378
(lldb) p (class_data_bits_t*)0x0000000100008378
(class_data_bits_t *) $2 = 0x0000000100008378
(lldb) p $2->data()
(class_rw_t *) $3 = 0x0000000101b06bc0
(lldb) p *$3
(class_rw_t) $4 = {flags = 2148007936witness = 0ro_or_rw_ext = {std::__1::atomic<unsigned long> = {Value = 4295000144}}firstSubclass = nilnextSiblingClass = NSUUID
}

好尴尬啊!class_rw_t里面没有看到我们该看到的信息啊!

class_rw_t


没有错啊!打印的信息和在class_rw_t源码里面的结构是一样的啊?
那怎么没有呢?我们刚打印的是结构信息,里面的方法没有找到,我们继续去看看源码,看看有没有打印属性的方法。

还真有方法,你说巧不巧啊!嘿嘿

那么靓仔,直接调用properties()不就可以了吗!

properties

(lldb) p $3.properties()
(const property_array_t) $5 = {list_array_tt<property_t, property_list_t, RawPtr> = {= {list = {ptr = 0x0000000100008198}arrayAndFlag = 4295000472}}
}Fix-it applied, fixed expression was: $3->properties()
(lldb)

调用properties()方法得到property_array_t

property_array_t

class property_array_t : public list_array_tt<property_t, property_list_t, RawPtr>
{typedef list_array_tt<property_t, property_list_t, RawPtr> Super;public:property_array_t() : Super() { }property_array_t(property_list_t *l) : Super(l) { }
};

list_array_tt

list_array_tt<property_t, property_list_t, RawPtr>


知道了结构,我们就一层一层的往下扒

(lldb) p $3.properties()
(const property_array_t) $5 = {list_array_tt<property_t, property_list_t, RawPtr> = {= {list = {ptr = 0x0000000100008198}arrayAndFlag = 4295000472}}
}Fix-it applied, fixed expression was: $3->properties()
(lldb) p $5.list
(const RawPtr<property_list_t>) $6 = {ptr = 0x0000000100008198
}
(lldb) p $6.ptr
(property_list_t *const) $7 = 0x0000000100008198
(lldb) p $7*
error: <user expression 9>:2:1: expected expression
;
^
(lldb) p *$7
(property_list_t) $8 = {entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $8.get(0)
(property_t) $9 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
(lldb) p $8.get(1)
(property_t) $10 = (name = "hobby", attributes = "T@\"NSString\",C,N,V_hobby")
(lldb)

还有谁?靓仔看到没有,JPPerson的属性打印出来了,我们要的类的信息成功输出来了!我这该死的魅力啊!

methods()

上面打印了属性,接下来该看看方法了

(lldb) p $3.methods()
(const method_array_t) $15 = {list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {= {list = {ptr = 0x0000000100008098}arrayAndFlag = 4295000216}}
}Fix-it applied, fixed expression was: $3->methods()
(lldb) p $15.list.ptr
(method_list_t *const) $18 = 0x0000000100008098
(lldb) p *$18
(method_list_t) $19 = {entsize_list_tt<method_t, method_list_t, 4294901763, method_t::pointer_modifier> = (entsizeAndFlags = 27, count = 6)
}
(lldb) p $19.get(0)
(method_t) $20 = {}
(lldb) p $19.get(0)
(method_t) $21 = {}
(lldb) p $19.get(1)
(method_t) $22 = {}

what ??什么鬼啊?怎么get打印不出来啊?别急继续探索下去

method_t


在源码里面发现了method_t结构体,里面嵌套了一个big结构体,big里面有个SEL 还有imp

那么可以通过method_t结构体拿到big,就可以获取到里面的方法,源码里面也发现了获取big方法big()

big()

(lldb) p $19.get(0).big
(method_t::big) $23 = {name = "sayHello"types = 0x0000000100003f94 "v16@0:8"imp = 0x0000000100003cd0 (JPObjcBuild`-[JPPerson sayHello])
}Fix-it applied, fixed expression was: $19.get(0).big()
(lldb) p $19.get(1).big
(method_t::big) $24 = {name = "hobby"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003d40 (JPObjcBuild`-[JPPerson hobby])
}Fix-it applied, fixed expression was: $19.get(1).big()
(lldb) p $19.get(2).big
(method_t::big) $25 = {name = "setHobby:"types = 0x0000000100003f9c "v24@0:8@16"imp = 0x0000000100003d70 (JPObjcBuild`-[JPPerson setHobby:])
}Fix-it applied, fixed expression was: $19.get(2).big()
(lldb) p $19.get(3).big
(method_t::big) $26 = {name = "init"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003c70 (JPObjcBuild`-[JPPerson init])
}Fix-it applied, fixed expression was: $19.get(3).big()
(lldb) p $19.get(4).big
(method_t::big) $27 = {name = "name"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003ce0 (JPObjcBuild`-[JPPerson name])
}Fix-it applied, fixed expression was: $19.get(4).big()
(lldb) p $19.get(5).big
(method_t::big) $28 = {name = "setName:"types = 0x0000000100003f9c "v24@0:8@16"imp = 0x0000000100003d10 (JPObjcBuild`-[JPPerson setName:])
}Fix-it applied, fixed expression was: $19.get(5).big()

干的漂亮!哈哈

iOS底层探索之类的结构(中):bits相关推荐

  1. iOS底层探索二(OC 中 alloc 方法 初探)

    前言 相关文章: iOS底层探索一(底层探索方法) iOS底层探索三(内存对齐与calloc分析) iOS底层探索四(isa初探-联合体,位域,内存优化) iOS底层探索五(isa与类的关系) iOS ...

  2. iOS底层探索(二) - 写给小白看的Clang编译过程原理

    iOS底层探索(一) - 从零开始认识Clang与LLVM 写在前面 编译器是属于底层知识,在日常开发中少有涉及,但在我的印象中,越接近底层是越需要编程基本功,也是越复杂的.但要想提升技术却始终绕不开 ...

  3. iOS 底层探索篇 —— KVC 底层原理

    iOS 底层探索篇 -- KVC 底层原理 1. Method Swizzling的坑与应用 1.1 method-swizzling 是什么? 1.2 坑点 坑点1:method-swizzling ...

  4. iOS 底层探索 - 消息转发

    一.动态方法解析流程分析 我们在上一章<消息查找>分析到了动态方法解析,为了更好的掌握具体的流程,我们接下来直接进行源码追踪. 我们先来到 _class_resolveMethod 方法, ...

  5. iOS底层基础知识-文件目录结构

    一:iOS沙盒知识 出于安全考虑,iOS系统把每个应用以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件.网络资源等(也有例外,比如系统通讯录.照相机.照片等能在用户授权 ...

  6. Swift: iOS底层基础知识-文件目录结构

    一:iOS沙盒知识 出于安全考虑,iOS系统把每个应用以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件.网络资源等(也有例外,比如系统通讯录.照相机.照片等能在用户授权 ...

  7. ios底层核心模板结构 - list_array_tt entsize_list_tt

    探索objc底层原理过程中,经常会碰到一个模板 list_array_tt 你在类加载,方法查找,散列表,同步锁等等都会碰到这个结构,c++的模板功能十分强大,但代码看上去确实比较头疼 其实没那么糟了 ...

  8. app启动页数秒加载 代码_iOS 底层探索 - 应用加载

    一.前导知识 以下参考自 WWDC 2016 Optimizing App Startup Time : 1.1 Mach-O Mach-O is a bunch of file types for ...

  9. iOS底层原理之架构设计

    文章目录 何为架构? MVC - Apple版 MVC – 变种 MVP MVVM 设计模式 面试题 何为架构? 架构(Architecture):软件开发中的设计方案,类与类之间的关系.模块与模块之 ...

  10. iOS底层原理总结 - OC对象的本质

    苹果官方文档 The Objective-C language defers as many decisions as it can from compile time and link time t ...

最新文章

  1. Matlab标识指令中字符的精细控制
  2. 【算法】螺旋方阵 上交OJ1021
  3. ORC文件存储格式的深入探究
  4. 设计模式(C++实现)--一句话总结
  5. element元素 取属性_js element类型的属性和方法整理
  6. js Promise理解,同时请求多个接口等
  7. 用python写网络爬虫-英文翻译
  8. MapInfo中MIF文件和MID文件的格式
  9. 程序员 -- 当我彻底放弃自私自利后,前途变得一片光明,不能过多的只是关注自己的功夫,生活不能只局限在方寸虚拟世界里
  10. 浏览器点击复制内容并打开微信
  11. Cadence PVS (Physical Verification System) rule 语法详解
  12. 关于TopoJSON以及制作方法
  13. 青龙-聚看点(稳定的毛)
  14. django批量修改table_Django 使用 modelformset 组件批量修改表单数据
  15. 界面原型设计工具开源软件
  16. 这些东西适合做什么?
  17. OD常用断点函数(转载)
  18. Ubuntu怎么查看电脑配置(ubuntu怎么查看系统配置)
  19. Python qrcode模块(生成二维码)
  20. 模拟浏览器操作程序(数据结构课设)

热门文章

  1. JS实现new关键字的功能
  2. linux 英汉词典程序shell+postgresql版
  3. Django 2.0.1 官方文档翻译: 文档目录 (Page 1)
  4. 构建根文件系统之busybox
  5. 自定义View调用onDraw方法
  6. cf1063A Oh Those Palindromes (贪心)
  7. Spring Security 3多用户登录实现之二 多登录界面展示
  8. C++ getline在VC6.0的一个bug(处理方法)(转)
  9. 编译运行Cube_slam
  10. Docker 容器的数据管理