本系列博客是本人的源碼閱讀筆記影所,如果有 iOS 開發(fā)者在看 runtime 的,歡迎大家多多交流。
但大家心中的問題可能也接踵而至:
- 方法 _getObjc2NonlazyClassList 作用是什么?
- 什么是 remapped_class_map ?
- 什么時(shí)候 創(chuàng)建 remapped_class_map 雨饺?以及什么時(shí)候 addRemappedClass ?
分析
對(duì)于第一個(gè)問題惑淳,相信大家稍微 Google 一下就會(huì)有結(jié)果:
NonlazyClass is all about a class implementing or not a +load method.
All the classes implemented in a given image file have a reference in a list stored in the "__DATA, __objc_classlist, regular, no_dead_strip" binary's section. This list allows the runtime system to keep track of all the classes stored in such file. However, not all of the classes need to be realized when the program starts up. That's why when a class implements a +load method, it also has a reference in a list stored in the "__DATA, __objc_nlclslist, regular, no_dead_strip" section.
So, _getObjc2NonlazyClassList retrieves the list of classes that do implement a +load method and are so called non-lazy. _getObjc2ClassList retrieves a list of all the classes in a image file, including the classes that don't have a +load method (and are called lazy) and the non-lazy ones. Non-lazy classes must be realized when the program starts up. Lazy classes, on the other hand, don't need to be realized immediately. This may be delayed until the class receives a message for the first time, for example (that's the reason for them to be considered "lazy").
The same is true for categories, by the way.
以上引用來自:Objective-C: What is a lazy class?
也就是說额港,如果一個(gè)類實(shí)現(xiàn)了 +load 方法,那么它就是個(gè) NonlazyClass汛聚。筆者為了證實(shí)這一點(diǎn)锹安,做了個(gè)驗(yàn)證:
// Realize non-lazy classes (for +load methods and static instances)
for (EACH_HEADER) {
classref_t *classlist =
_getObjc2NonlazyClassList(hi, &count);
for (i = 0; i < count; i++) {
Class cls = remapClass(classlist[i]);
//這里加了代碼用于測(cè)試
if (0 == strcmp(cls->mangledName(), "TestObject")) {
printf("TestObject is non-lazy Class\n");
fflush(stdout);
}
if (!cls) continue;
realizeClass(cls);
}
}
其中,TestObject 的定義如下:
@implementation TestObject
+(void) load {
}
int MyWeakLinkedFunction () {
return 1;
}
@end
那么,另外一個(gè)問題來了:
有多少 non-lazy class 叹哭?同樣的忍宋,筆者寫了如下代碼,打印出所有的 non-lazy class :
// Realize non-lazy classes (for +load methods and static instances)
for (EACH_HEADER) {
classref_t *classlist =
_getObjc2NonlazyClassList(hi, &count);
for (i = 0; i < count; i++) {
Class cls = remapClass(classlist[i]);
//這里加了代碼用于測(cè)試
printf("non-lazy Class:%s\n",cls->mangledName());
fflush(stdout);
if (!cls) continue;
realizeClass(cls);
}
}
打印的結(jié)果總結(jié)到筆者的GitHub了:non-lazy-classes.txt
可以看到风罩,大概有60個(gè) non-lazy-classes糠排。
什么時(shí)候創(chuàng)建 remapped_class_map ?
其實(shí)函數(shù)
static NXMapTable *remappedClasses(bool create)
已經(jīng)告訴我們了超升。
參數(shù) create 告訴是否需要?jiǎng)?chuàng)建 hash map入宦,在 _read_images 方法中傳進(jìn)來的參數(shù)都是 NO,也就是說不會(huì)主動(dòng)創(chuàng)建 hash map室琢。我們?nèi)炙阉饕幌?remappedClasses乾闰,可以發(fā)現(xiàn)確實(shí)有地方調(diào)用的時(shí)候 傳入的參數(shù)是 YES:
static void addRemappedClass(Class oldcls, Class newcls) {
...
old = NXMapInsert(remappedClasses(YES), oldcls, newcls);
...
}
可以發(fā)現(xiàn)確實(shí)創(chuàng)建了,也就是我們前文所說的 addRemappedClass 方法盈滴。那
什么時(shí)候調(diào)用 addRemappedClass 方法涯肩?
但是并不是所有情況下都會(huì)調(diào)用到,只要查看一下函數(shù) readClass 的實(shí)現(xiàn)就知道:
本文暫不做介紹了巢钓,后面的文章中會(huì)給大家介紹病苗。
總結(jié)
本文終于又講完一個(gè) hashmap:remapped_class_map。其實(shí)說白了很簡(jiǎn)單症汹,remapped_class_map 就是存儲(chǔ)了 non-lazy classes 的