iOS开发之 runtime(29) :gdb_objc_realized_classes 浅析

本系列博客是本人的源码阅读笔记,如果有 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 是一系列的类列表,这些类不管有没有实现都不在 dyld 的共享缓存中。
全局搜索 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 分析结束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章