mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: SSL/TLS
This commit is contained in:
@@ -2,6 +2,58 @@
|
||||
|
||||
> 做很多需求或者是技术细节验证的时候会用到 Runtime 技术,用了挺久的了,本文就写一些场景和源码分析相关的文章。
|
||||
|
||||
## 动态语言
|
||||
|
||||
Runtime 是实现 OC 语言动态的 API。
|
||||
|
||||
静态语言:在编译阶段确定了变量数据类型、函数地址等,无法动态修改。
|
||||
|
||||
动态语言:只有在运行的时候才可以决定变量属于什么类型、方法真正的地址,
|
||||
|
||||
对象 `objc_object` 存了:isa、成员变量的值
|
||||
|
||||
类 objc_class: superclass、成员变量、实例变量
|
||||
|
||||
```objectivec
|
||||
@interface Person : NSObject
|
||||
{
|
||||
NSString *_name;
|
||||
}
|
||||
@property (nonatomic, strong) NSString *hobby;
|
||||
@end
|
||||
|
||||
malloc_size((__bridge const void *)(p)) // 24 isa占8字节 + _name 指针占8字节 + hobby 指针占8字节 = 24
|
||||
class_getInstanceSize(p.class) // 32 ,系统内存对齐
|
||||
```
|
||||
|
||||
为什么内存对齐?以空间换时间。系统以16字节对齐。
|
||||
|
||||
x /6gx p.class
|
||||
|
||||
类对象有且仅有1个。
|
||||
|
||||
p.class
|
||||
|
||||
class_getClass("Person")
|
||||
|
||||
[Person class]
|
||||
|
||||
p/x (class_data_bits_t *)地址
|
||||
|
||||
## class_rw_t、class_ro_t 区别?
|
||||
|
||||
class_ro_t 在编译时期生成的,class_rw_t 是在运行时期生成的。
|
||||
|
||||
拷贝带来的问题?当开发者通过 runtime第一次 动态修改类的信息的时候,Apple 会生成 rwe。搜索 class_rw_ext_t
|
||||
|
||||
## 有类对象、为什么设计元类对象
|
||||
|
||||
复用消息机制。比如 `[Person new]`。
|
||||
|
||||
元类对象: isa、元类方法、
|
||||
|
||||
`objc_msgSend` 设计初衷就是为了消息发送很快。假如没有元类,则类方法也存储在类对象的方法信息中,则可能需要加额外的字段来标记某个方法是类方法还是对象方法。遍历或者寻找会比较慢。所以引入元类(单一职责),设计元类的目的就是为了提高 `objc_msgSend` 的效率。
|
||||
|
||||
## isa 本质
|
||||
|
||||
在 arm64 架构之前,isa 就是一个普通的指针,存储着 Class或Meta-Class 对象的内存地址。
|
||||
@@ -89,7 +141,7 @@ isa 在 arm64 之后必须通过 `ISA_MASK` 去查询 class(类对象、元类
|
||||
|
||||
`0x0000000ffffffff8ULL` 用程序员模式打开计算器
|
||||
|
||||

|
||||

|
||||
|
||||
其中,结构体中的数据存放大体是下面的结构:
|
||||
|
||||
@@ -291,7 +343,7 @@ struct class_ro_t {
|
||||
|
||||
具体关系整理如下图
|
||||
|
||||

|
||||

|
||||
|
||||
说明:
|
||||
|
||||
@@ -299,7 +351,7 @@ struct class_ro_t {
|
||||
|
||||
为什么不是二维数组?因为Array 中的子 Array长度不一致,且不能补空
|
||||
|
||||

|
||||

|
||||
|
||||
```c
|
||||
static void remethodizeClass(Class cls)
|
||||
@@ -384,7 +436,7 @@ struct class_ro_t {
|
||||
|
||||
- `class_ro_t` 里面的 baseMethodList、baseProtocols、ivars、baseProperties 是一维数组,是只读的,包含了类的(原始信息)初始内容
|
||||
|
||||

|
||||

|
||||
|
||||
## Method_t
|
||||
|
||||
@@ -422,7 +474,7 @@ typedef struct objc_selector *SEL;
|
||||
|
||||
iOS 中提供了一个叫做 `@encode` 的指令,可以将具体的类型表示成字符串编码
|
||||
|
||||

|
||||

|
||||
|
||||
```objectivec
|
||||
- (int)calcuate:(int)age heigith:(float)height;
|
||||
@@ -774,7 +826,7 @@ NSLog(@"%s %p", bucket._key, bucket._imp);
|
||||
// personSay 0xbec8
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
原理就是根据类对象结构体找到 cache 结构体,cache 结构体内部的 `_buckets` 是一个方法散列表,查看源代码,根据散列表的哈希寻找策略 `(key & mask)` 找到哈希索引,然后找到方法对象 bucket,其中寻找方法索引的 key 就是 方法 selector。
|
||||
|
||||
@@ -1359,7 +1411,7 @@ for 循环不断查找,找当前类的父类,直到当前类为 nil。
|
||||
|
||||
上面的流程是整个 `objc_msgSend` 的消息发送阶段的整个流程。可以用下图表示
|
||||
|
||||

|
||||

|
||||
|
||||
### 动态方法解析阶段
|
||||
|
||||
@@ -1494,7 +1546,7 @@ SEL_resolveClassMethod, sel);`
|
||||
|
||||
完整流程如下
|
||||
|
||||

|
||||

|
||||
|
||||
上 Demo
|
||||
|
||||
@@ -1634,7 +1686,7 @@ void *_objc_forward_handler = (void*)objc_defaultForwardHandler;
|
||||
|
||||
为什么是 `__forwarding__` 方法。我们可以根据 Xcode 崩溃窥探一二
|
||||
|
||||

|
||||

|
||||
|
||||
```c
|
||||
int __forwarding__(void *frameStackPointer, int isStret) {
|
||||
@@ -1678,7 +1730,7 @@ int __forwarding__(void *frameStackPointer, int isStret) {
|
||||
|
||||
完整流程如下
|
||||
|
||||

|
||||

|
||||
|
||||
上 Demo
|
||||
|
||||
@@ -1899,7 +1951,7 @@ objc_msgSendSuper(arg, sel_registerName("class"))
|
||||
|
||||
我们对 iOS 项目`[super viewDidLoad]` 下符号断点,发现`objc_msgSendSuper2`
|
||||
|
||||

|
||||

|
||||
|
||||
查看 objc4 源代码发现是一段汇编实现。
|
||||
|
||||
@@ -2133,7 +2185,7 @@ void test () {
|
||||
|
||||
方法内的变量存储在栈上,堆向上增长,栈向下增长。
|
||||
|
||||

|
||||

|
||||
|
||||
3.**实例对象的本质就是一个结构体,存储所有成员变量(isa 是一个特殊成员变量,其他的成员变量,这里就是 _name),`sayHi` 方法内部的 self 就是 obj,找成员变量的本质就是找内存地址的过程(此时就是偏移8个字节)**
|
||||
|
||||
@@ -2182,7 +2234,7 @@ objc_msgSendSuper(arg, sel_registerName("viewDidLoad"));
|
||||
|
||||
所以此时的“前一个局部变量” 也就是结构体 `objc_super` 类型的 arg。arg 是一个结构体,结构体第一个成员变量就是 self,所以“前一个局部变量” 也就是 self(ViewController)
|
||||
|
||||

|
||||

|
||||
|
||||
## 应用场景
|
||||
|
||||
@@ -2216,7 +2268,7 @@ Person *p = [Person new];
|
||||
object_setClass(p, [Student class]);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
3.动态创建类
|
||||
|
||||
@@ -2243,7 +2295,7 @@ void createClass (void) {
|
||||
}
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
runtime 中 copy、create 等出来的内存,不使用的时候需要手动释放`objc_disposeClassPair(newClass>)`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user