iOS开发之 runtime(29) :gdb_objc_rea
本系列博客是本人的源码阅读笔记,如果有 iOS 开发者在看 runtime 的,欢迎大家多多交流。为了方便讨论,本人新建了一个微信群(iOS技术讨论群),想要加入的,请添加本人微信:zhujinhui207407,【加我前请备注:ios 】,本人博客http://www.kyson.cn 也在不停的更新中,欢迎一起讨论
本文完整版详见笔者小专栏:https://xiaozhuanlan.com/runtime
概述
我们在iOS开发之runtime(27): _read_images 浅析中讲解了 class 相关的多个 hash 表:
- gdb_objc_realized_classes
- remapped_class_map
- future_named_class_map
- nonmeta_class_map
本文我们就详细的分析一下这几个 hash map 的第一个: gdb_objc_realized_classes。
gdb_objc_realized_classes
gdb_objc_realized_classes is actually a list of named classes not in the dyld shared cache, whether realized or not.
这段文字出现在文件 objc_runtime_new.mm 中:
gdb_objc_realized_classes
这里翻译一下:
gdb_objc_realized_classes 是一系列的类列表,这些类不管有没有实现都不在 dyld 的共享缓存中。
全局搜索 gdb_objc_realized_classes,我们可以看到一系列方法,
搜索 gdb_objc_realized_classes
这些方法涉及到对于 gdb_objc_realized_classes 的一系列操作,包括:
获取某个类:
static Class getClass_impl(const char *name)
{
runtimeLock.assertLocked();
// allocated in _read_images
assert(gdb_objc_realized_classes);
// Try runtime-allocated table
Class result = (Class)NXMapGet(gdb_objc_realized_classes, name);
if (result) return result;
// Try table from dyld shared cache
return getPreoptimizedClass(name);
}
添加某个类:
/***********************************************************************
* addNamedClass
* Adds name => cls to the named non-meta class map.
* Warns about duplicate class names and keeps the old mapping.
* Locking: runtimeLock must be held by the caller
**********************************************************************/
static void addNamedClass(Class cls, const char *name, Class replacing = nil)
{
runtimeLock.assertWriting();
Class old;
if ((old = getClass(name)) && old != replacing) {
inform_duplicate(name, old, cls);
// getNonMetaClass uses name lookups. Classes not found by name
// lookup must be in the secondary meta->nonmeta table.
addNonMetaClass(cls);
} else {
NXMapInsert(gdb_objc_realized_classes, name, cls);
}
assert(!(cls->data()->flags & RO_META));
// wrong: constructed classes are already realized when they get here
// assert(!cls->isRealized());
}
移除某个类:
/***********************************************************************
* removeNamedClass
* Removes cls from the name => cls map.
* Locking: runtimeLock must be held by the caller
**********************************************************************/
static void removeNamedClass(Class cls, const char *name)
{
runtimeLock.assertWriting();
assert(!(cls->data()->flags & RO_META));
if (cls == NXMapGet(gdb_objc_realized_classes, name)) {
NXMapRemove(gdb_objc_realized_classes, name);
} else {
// cls has a name collision with another class - don't remove the other
// but do remove cls from the secondary metaclass->class map.
removeNonMetaClass(cls);
}
}
而初始化的位置就是我们所知道的 _read_images 方法中:
// namedClasses
// Preoptimized classes don't go in this table.
// 4/3 is NXMapTable's load factor
int namedClassesSize =
(isPreoptimized() ? unoptimizedTotalClasses : totalClasses) * 4 / 3;
gdb_objc_realized_classes =
NXCreateMapTable(NXStrValueMapPrototype, namedClassesSize);
add 方法的也位于 _read_images 调用栈中:
- void _objc_init(void)
- void _dyld_objc_notify_register();
- void map_2_images();
- void map_images_nolock();
- void _read_images();
- Class readClass();
- void addNamedClass();
需要注意的是:
addNamedClass(cls, mangledName, replacing);
的第二个参数是 mangledName, 也就是上一篇文章笔者 Demo 中给大家从 section 中获取的数据。
现在看来,gdb_objc_realized_classes 的作用已经很明显了,即是对所有的类进行缓存:从对应的 section 中读取所有的类,取出来后以 mangledName 作为键,以 class 结构体作为值。
至此 gdb_objc_realized_classes 分析结束。
广告
我的首款个人开发的APP壁纸宝贝上线了,欢迎大家下载。