isa和类的走势图

iOS 类的结构剖析

从上图可得知

1、政策的isa 指向类,类的isa指向元类,元类的isa 指向根元类,根元类isa 指向根元类。

2、类承继父类,父类承继根父类,根父类承继 nil。元类承继父元类,父元类承继源码共享网根元类,根元类承继根父类。

类的结构

新版的objc源码和旧的objc是不一样的,这儿主要是剖析 新版的objc 源码。
新的源码版本是objc4-818.2

struc源码年代t变量名 objc_class : objc_object {
// 部分源码
// Class ISA;
Class superclass;
cache_t cache;             // formerly cache pointer and vtable
class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();源码
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
void setInfo(缓存视频uint32_t set) {算法的时刻复杂度是指什么
ASSERT(isFuture()  ||算法的有穷性是指  isRealized());
data()->setFlags(set);
}
void clearInfo(uint32_t clear) {
ASSERT(isFuture()  ||  i算法设计与剖析sRealized());
d源码编辑器a算法的时刻复杂度取决于ta()->clearFlags(clear);
}源码共享网
// 其他源码没有贴出来
}

这便是类的主要结构,其间superclass 是父类,ca源码年代che缓存bits 里边是办法缓存文件在哪里特征署理成员变量

1. cache 的结构

经过源码检查`cache_t` 的结构。能够看出`cache_t`是一个联合体域。

struct cache_t {
private:
explicit_atomic<uintptr_t> _源码共享网bucketsAndMaybeMask;
uni源码之家on {
struct {
explicit_atomic<mask_t>    _maybeMask;
#if __LP64__
uin变量类型有哪些t16_t                   _flags;
#endif
uint16_t                   _occupied;
};
explicit_atomic<preopt_cache_t *> _originalPreoptCache;
};
void increment源码编辑器手机版下载Oc缓存视频合并app下载cupied();
public:
// The following four fields are public for objcdt's use only.
// objcdt reaches into fields while the process is suspended
// hence doesn't care for locks and pesky little details like this
// and can safely use these.
unsigned capacity() const;
struct bucket_t *buckets() const;
Class cl缓存视频s() const;
void insert(SEL sel, IMP imp, id receiver);
};
JCPerson *p  = [JCPerson alloc]; //cl缓存文件在哪里a缓存视频ss_data_bits_t  cache_t
Class pClass = [JCPerson class];
//        p.name       = @"djc";
//        p.age        = 18;
[p sayHello];
[p sayCode];
[p sayMaster];

JCPerso变量值n经过断点调试lldb 检查

// 拿到类的地址
(lldb) p/x pClass
(Class) $0 = 0x00000001000082b0 JCPerson
// 经过廉变量与函数教案价地址拿到cache_t
(lldb) p (cac源码共享网he_t *)0x00000001000082c0
(cache_t *) $1 = 0x00000001000082c0
// 检查cache_t 结构
(lldb) p *$1
(cache_t) $2 = {
_bucketsAndMay缓存视频beMask = {
std::__1::atomic<unsigned long> = {
Value = 4298515408
}
}
= {
= {
_maybeMask = {
std::__1::atomic<unsigned int> = {
Value = 0
}
}
_flags = 32804
_occupied = 0
}
_originalPreoptCache = {
std::__1::atomic<pr缓存视频e缓存的视频怎样保存到本地opt_cache_t *> = {
Value = 0x0000802400000000
}
}
}
}
// 获得b变量与函数教案uckets
(lldb) p $2.buckets()
(bucket_t *) $3 = 0x00000001003623d0
(ll缓存视频变成本地视频db) p *$3
(bucket_t) $4 = {
_sel = {
std::缓存视频怎样转入相册__1::atomic<objc_selector *&源码本钱gt; = (null) {
Value = nil
}
}
_imp = {
std::__1::atomic源码编辑器<uns缓存视频怎样转入相册igned源码买卖网站源码 long> = {
Value = 0
}
}
}
// 检查sel
(lldb) p $4.sel()
(SEL) $算法的时刻复杂度是指什么5源码编辑器手机版下载 = (null)
  • 当没有实施sayHello 办法之前 p $4.sel() 得到的是null_occupied0;说明还没有缓存办法。
(lldb) p *$1
(cache_t) $8 = {算法工程师
_bucketsAndMaybeMask = {
std::__1::a变量与函数教案tomic<unsigned算法导论 long&算法的时刻复杂度是指什么gt; = {
Value = 4311840848
}
}
= {
= {
_maybeMask = {
std::__1::atomic<unsigned int> = {
Value = 3
}
}
_flags = 32804
_occupied = 1
}
_originalPreoptCache = {
std::__1::atomic<preopt_cac算法导论he_t *> = {
Value = 0x0001802400000003
}
}
}
}
(lldb) p $8.buckets()
(bucket_t *) $10 = 0x000000010101785
(lldb) p $10->sel()
(SEL) $12 = "sayHello"
  • 当实施sayHello源码年代 之后_occupied1p $10->sel() 回来 (SEL) $12 = "sayHello"
2. cache_t 缓存办法的原理

经过上面lldb调试看得出cache_t在实施办法之后会缓存办法,那么是怎样完结的呢?

void cache_t::insert(SEL sel,缓存的视频怎样保存到本地 IMP im变量类型有哪些p, id receiver)
{
// 部分源码
// 拿到个数
// Use the cache as-is if until we exceed our expected fill ratio.
mask_t newOccupi缓存整理ed = occupied() + 1;
unsigned oldCapacity = capacity(变量的定义), capacity = oldCapacity算法工程师;
// 当没有缓存的时分 分配缓存巨细
if (slowpath源码年代(isConstantEmptyCache())) {
/算法的时刻复杂度取决于/ Cache is read-only. Repl算法ace it.
if (!capacity) capacity = INIT_CACHE_SIZE;
// 分配INIT_CACHE_SIZE=4 的巨细
real算法的时刻复杂度是指什么locate(oldCapacity, capacity, /* freeOld */false);
}
else if源码编辑器编程猫下载 (fastpat源码年代h(newOc源码编辑器手机版下载cupied + CACHE_END_MARKER <= cache_fill_ratio(capacity))缓存视频在手机哪里找) {
/缓存视频怎样转入本地视频/ 缓存存在而且缓存的巨细小于3/4 或 7/8 什么都不做
/源码编辑器编程猫/ Cache is less than 3/4 or 7/8 full. Use it as-is.
}
#i缓存视频怎样转入本地视频f CACHE_ALLO源码买卖网站源码W_FULL_UTILIZATION
else if (源码共享网capacity <= FULL_UTILIZATION_CACHE_SIZE && newOc算法导论cupied + CACH缓存文件在哪里E_END_MARKER &l缓存视频变成本地视频t;= capa缓存city) {
// Allo源码本钱w 100% cache utilization源码年代 for small buckets. Use it as-is.
}
#endif
else {
// 当缓存存在,而且大于 现已分配的巨细时。
// 重源码编辑器手机版下载新分配缓存打小,打小为 从前的巨细 2倍
// 最大为 MAX_CACHE_SIZE = 1 &源码之家lt缓存;算法的五个特性< 16 巨细
capacity = capacity ? capacity * 2 : INIT_CACHE_SI变量名的命名规矩ZE;
if (capacit缓存的视频怎样保存到本地y > MAX_CACHE_SIZE) {
capacity = MAX_CACHE_SIZE;
}
reallocate(oldCapacity, capac算法的有穷性是指ity, true);
}
// 那到其时的办法
bu算法的时刻复杂度是指什么cket_t *b = buckets();
// 获取下标
mask_t m = capacity - 1;
// 将其时办法经过hash算法存储
mask_t begin = cache_hash(sel, m)算法剖析的意图是;
mask_t i算法的有穷性是指 = begin;
// Scan for the first unused slot and insert there.
// The源码年代re is guaranteed to be an empty slot.
// 循环 一切办法 ,经过hash 算法存储每个办法
do {
if (fastpa源码编辑器编程猫th(b[i].sel() == 0)) {
incrementOccupied();
b变量名的命名规矩[i].set<Atomic, Encoded>(b, sel, imp, cls());
return;
}
if (b[i].sel() == sel) {
// The entry was added to the cache by some other thread
// before we grabbed the cacheUpdateLock.
return;
}
} while (fastpath((i = cache_next(i, m)) != begin));
bad_cache(receiver, (SEL)变量与函数教案sel);
#endif // !DEBUG_TASK_THREADS
}

3算法是什么.bi变量之间的联系ts 结构

经过得到类的首地址,然后更具廉价量获得`bits`里边的内容`class_data_bits_t`。
`Person *p = [Person alloc];`
经过`变量x/4gx Pe缓存视频在手机哪里找rson.class` 获得首地址,然后偏移32位`p (class_data_bits_t *算法)0x100008220` 得到`bits` 信息,而且得到`class_rw_t`信息源码编辑器编程猫
(lldb) x/4gx Person.class
0x100008200: 0x00000001000081d8 0x000000010036a140
0x100008210: 0x00000001003623d0 0x0000802400000000
(lldb) p (class_data_bits_t *)0x100008220
(class_data_bits_t *) $3 = 0x0000000100008200
(lldb) p $3->data()
(class_变量是什么意思rw_t *) $4 = 0x00000001000081d8
(lldb) p *$4
(class源码编辑器_rw_t) $5 = {
flags = 3580144
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned lon算法是什么g> = {
Value = 4298547440
}
}
firstSubclass = 0x000000010070fd40
nextSiblingCla源码本钱ss = 0x0002e03500000003
}
struct class_rw_t {
// Be warned tha源码之家t Symbolic源码网站ation knows the layout of this structure.
// 有部分代码没有贴出来
...
public:
// 成员源码买卖网站源码变量列表
const class_ro算法的有穷性是指_t *ro() c算法的时刻复杂度取决于onst {
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.变量泵get&lt缓存文件在哪里;class_rw_ext_t *>(&amp变量是什么意思;ro_or_rw_ext)->r算法的有穷性是指o;
}
ret算法剖析的意图是urn v.get<const class_ro_t *>(&ro_or_rw_ext);
}
vo算法工程师id set_ro(const class_ro_t *ro) {
auto v = get_ro_or_rwe();
if (变量与函数v.is<class_rw_ext_t *变量名的命名规矩>()) {
v.get<class_rw_ext_t *>(&amp算法设计与剖析;ro_or_rw_ext)->ro = ro;
} else {
set_ro_or_r源码网站we(ro);
}
}
// 办法列表
const method_array_t methods() 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)->methods;
} else {
return method_array_t{v.get<算法工程师const class_ro_t *缓存视频>(&ro_or_rw_ext)->baseMethods()};
}
}
// 特征办法列表
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_变量是什么意思arr变量名的命名规矩ay_t{v.变量值get<const class_ro_t *&算法是什么gt;(&ro_or_rw_ext源码)->basePrope缓存视频rties};
}
}
// 署理办法列表
const protocol_array_t protocols() const {
auto v = g变量名的命名规矩et_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get缓存的视频怎样保存到本地<class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
} else {
return protocol_array_t{v.get<const cl算法工程师和程序员差异ass_r源码年代o_t *>(&ro_or_rw_ext)->baseProtocols};
}
}
};

检查类里边的特征``办法`变量`署理办法下面已检查特征办法为例

// 检查特征办法
(lldb) p $4->properties()
(const property_array变量值_t) $5 = {
list_array_tt<property_t, property_list_t, RawPt源码编辑器编程猫r> = {
= {
list = {
ptr = 0x0000000100008220
}
arrayAndFlag = 4295000608
}
}
}
(lldb) p $5.list
(const RawPtr<property_list_t>源码本钱) $6 = {
ptr = 0x0000000100008220
}
(lldb) p缓存视频变成本地视频 $6.ptr
(property_l缓存的视频怎样保存到本地ist_t *const) $7 = 0x0000000100008220
(lldb) p *$7
(property_list_t)算法的时刻复杂度是指什么 $7 = {
entsize_l缓存视频合并app下载ist_tt<p算法工程师roperty_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $7.get(0)
(proper源码编辑器手机版下载ty_t) $8 = (name = "name", attributes = "T@"NSString",C,N,V_name")