Those things runtime (c) - NSObject initialization load and initialize

From the runtime source code level to study under NSObject class initialization related methods: load, initialize, and inside when you call what has been done

table of Contents


A, load method

 1. load_images

 2. call_load_methods

Two, initialize method


A, load method

+(void) load;

 As iOS development, how many have had dealings with the load method - in the program mainbefore the function call, when the class is loaded into memory registered, loadthe method will be called. That each class loadmethod is called once.
 In this method, we most commonly used scenes runtime function is to use the exchange offer OBJC_EXPORT void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2), to change the behavior of a system and method to add custom behavior.
But to understand the internal load method implementation process, to begin the process had to start from the iOS program.

 In the program main()before the function executes, in turn do the following work:

  1. System load App itself all 可执行文件(Mach-O file), and obtain dyldthe path (dyld is designed to load the dynamic link library);
  2. dyldInitializing the operating environment, and open dyld 缓存策略(primarily distinguished from a cold start and warm start of App), starting from the order dependent executable recursively load all dependent dynamic link library, the library by all dependent dyldachieved inside the Mach-O file instantiated for the imageimage file.

Note: The dynamic link library include: all systems framework, system-level libSystem (libdispatch, libsystem_blocks etc.), load libobjc Objective-C runtime (ie Objective-C runtime initialization)

  1. When dyldperformed after the class structure initializes all dependencies in the initialization and runtime will project all classes, then 调用所有类的 load 方法;
  2. dyld will eventually return main()address of the function, main()the function is called, and then the program will enter the familiar entrance default from the AppDelegateclass begins.

 This section is only Load method to load the analysis, so the dynamic link library on dyld not start.
 Add a breakpoint in a class load method, the compiler run, invoke the console lldb in btcommand, you can view the complete call stack information.

1243805-79ea8c79506aa11b.png

Stack information, after dyld finished loading the dynamic link library, the class load before the method, runtime calls two functions: load_images and call_load_methods .

1. load_images

First look at the load_images

1243805-828fc792766ed466.png

 The first step, will not quickly turn lockable load method to check whether there are classes and categories, this is a comment in the runtime, really speaking, not lockable load method, did not understand. With curiosity to look at bool hasLoadMethods(const headerType *mhdr) function implementation, found _getObjc2NonlazyClassList with _getObjc2NonlazyCategoryList .
1243805-fb961e8370722d2f.png

Program initialization process, all class class implementation are in a binary image stored in the image file list, and will have a reference in the list, this list will allow binary runtime to track access to retrieve the stored class, but not all classes We will have will be realized when the program starts. So when a class implements load method, also add a reference index in the binary list, let runtime to track access. And this list is stored in the image binary image file "__DATA, __objc_nlclslist, regular, no_dead_strip " section (follow-up article seems to go in-depth understanding of the dynamic link library dyld)
 in _getObjc2NonlazyClassList search of an array of class has achieved load a class method, in which non-lazy load class. Non-lazy loading load class method will be realized when the program starts, the corresponding class has not lazy loading implementation. Lazy loading method of loading load class category will delay the first received message. Similarly, _getObjc2NonlazyCategoryList acting on the classification, with _getObjc2NonlazyClassList the same function.
 When retrieving lazy loading classes, the need to use _getObjc2ClassList and _getObjc2CategoryList , respectively, to retrieve all classes (class including a non-lazy loading, lazy loading classes), extended classification (class including a non-lazy loading, lazy loading class).
 Therefore, the bool hasLoadMethods(const headerType *mhdr) function of the role is to query all non-lazy loading classes, the existence of methods of a loaded load class extends the array. But why this function is annotated in runtime in: fast scan is not lockable load method. For non-lazy load method to load the class is defined as not lockable load method in runtime in? Up to now I have been having this question.

 The second step, when it is determined there is a non category lazy loading, class extended load method, with the thread will first locking mutex, and performs void prepare_load_methods(const headerType *mhdr)a function.

1243805-e4bc853c6b045dc1.png

 In the void prepare_load_methods(const headerType *mhdr) function, traverse _getObjc2NonlazyClassList function in the loaded load method of the class, and class pointers to get the currently active (because the class pointer may point to the class structure has been re-assigned; and would ignore the weak link, return nil), recursively to find the currently valid connection type as well as the parent does not call the load method, added to the executable load method to load the array. Moreover, in order to ensure that the parent class to call the load method before subclasses, through static void schedule_class_load(Class cls) recursive function to achieve.
1243805-76db266e4937246c.png

 Finally, void add_class_to_loadable_list(Class cls) the function, which has been in an active state is connected to a loadable class to add load an array of class methods, and the method will load the class corresponding to maintain IMP added into a specialized load array maintenance process. Function declaration can also be found by recursively let superclass first class execution of void add_class_to_loadable_list(Class cls) the function, to ensure that when the super class does not implement load method, add the super class to be loaded load array method, followed by the class and then added to the array.
1243805-c980d1d2a58673c1.png

 When the non-lazy loading executable to load class traverses through the array of class methods, then the classification is also performed on all of the same operation, and a method and corresponding classification to maintain IMP in the corresponding array. However, the classification traversal process, will first perform class classification corresponding to static Class realizeClass(Class cls) a function operation to initialize the class. About static Class realizeClass(Class cls) the role of the function, the former articles of those things runtime (b) - NSObject data structure has to do that in order to be able to make the corresponding category classification information loaded into the class structure, the class must first be initialized.
 When the non-lazy loading type, classification information, and a corresponding method of IMP ready load, will enter into the next call_load_methods() function.

2. call_load_methods

call_load_methods Function declaration.

1243805-f99b807f87ce2528.png

About call_load_methods the role of the function, runtime source has given a very good explanation.

  1. Priority call load method for all classes, go to the implementation of load classification method;
  2. Parent load method for performing priority subclass;
  3. This function allows the declaration is executed more than once, because the load loading process will trigger more image map image file, and call the load method is through dyld (dynamic link library) dyld_register_image_state_change_handler, each time there is a new image file is added trigger (do not call here dyld expansion);
  4. Do while loop is repeated by a call to load the class methods, can be loaded until the load is no longer class methods;
  5. load classification method only once, in order to ensure that the "parent first" call to order, it will trigger a new class can be loaded even when the class loader;
  6. In the do while loop is executed during the load method, in order to ensure thread safety, loadMethodLockmust be held by the caller, no other lock can not be held.

On the outside do while loop, using autoreleasePool management. Whenever cycle is finished, it will be cleared up temporary variables and memory resources consumed to produce intermediate process.

call_class_loads() 与 call_category_loads()

The above-described two methods are traversed call load method and classification class

1243805-f44ff5d97286e5f5.png
call_class_loads () method implementation

 When the call load method, and not by objc_msgSend() transmitting a message method, but direct access to a memory address corresponding to the class load method to invoke (*load_method)(cls, SEL_load); , which is called the most significant features is call between classes, the parent class, load classification method is not will influence each other, when implementing the load method of the class, will not take the initiative to call the load method of the parent class. In other words, to achieve the load class method without calling [super load]; the method.

In the call_category_loads()method, the call_class_loads()method call is slightly different.

  • Loadable load method first array of free copying a same array of structures, named cats;
  • After cats array traversal load load classification method (also called through direct access to the load method of memory address), it will remove the loaded load classification method from the cats;
  • Check again loadable_categoriesif there is classification of new loadable load method of the array, if present, to determine whether the classification of an array of memory has been fully occupied, if fully occupied then be expanded on the basis of the current array of memory on the call reallocfor dynamic allocation of memory modification, and then added to the new classification in cats;
  • The destruction of the original loadable_categories
  • If there is a new classification was added, the destruction cats array loadable_categoriesparameters all set to an initial state, and return NO, represents all of Classification methods have been loaded to complete the load; if the presence of added free cats new array, the array will assign cats to loadable_categories, and finally return YES, it represents the new classification and the added need to load its load method.

summary

From the runtime source code level to study the method of loading load, which has also been on some of the characteristics of the load method.

  1. Load a program loading method in the initialization phase, runtime initialization process load_imagesperformed;
  2. The method of the parent class load will load in preference to execution method subclass;
  3. The method of performing load all classes former, load subsequent execution of the method of classification;
  4. A class code calls active without load method, class, subclass, the method will be executed once load;
  5. In the process load necessary to call [super load]the method, the internal recursive search will traverse up and execute its parent load method;
  6. Class load method to load the main project is in the final stages dyld call dynamic link library, dynamic library load method means that the project will be introduced in class load method takes precedence over the main project execution;

Of course, there are other methods load characteristics, such as:
the same image file image, there is no relationship between the order of two classes call the load method, the order of execution is in accordance with the Compile Sources class files;
the same mirror image files, each class If the classification method to achieve the load will to perform, the order of execution is in accordance with the classification document in order Compile Sources in;


Two, initialize method

+(void) initialize;

Calls on the timing of the initialize method, when it will call the initialize method?
 When introducing a class does not do anything with it, when, and not trigger initialize method of execution; only in this category for the first time to send the message that triggered calls objc_msgSend()upon method, only to do it.

1243805-8326f3da7bd1a014.png
Calls the initialize method

On IMP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver) , whose role is to find methods to achieve IMP, it has a pivotal role in the process to send a message class.
In the source code, when the class for the first time a message is received, judges that the initialization method and no need to initialize initialize method is performed, it will to perform void _class_initialize(Class cls) the method, and performs the protection of the locking initialize method.
1243805-d4cb4942000cc333.png

In the void _class_initialize(Class cls) method, first go to recursively check whether the parent has been executed initialize method.
Then, the current class is determined mask bit arithmetic flags is not RW_INITIALIZED the RW_INITIALIZING time, which is provided to bit mask flags RW_INITIALIZING , to flag for the initialize method. By atomic protection against initialize method is repeatedly performed.
Finally, to execute callInitialize(cls); methods, and implementation of this method is also very simple ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize); . Different from the load method of execution, use objc_msgSend() messaging to perform SEL_initialize selector, did not like the same way as load directly selector memory address to call. Since it is used objc_msgSend to go messaging process, when the child had not realized, it will call the parent class implementation inheritance; if classification implements the initialize method, it will take precedence (initialize method in this class classification was achieved not covered , and there is still kind of information, simply because classification and priority to achieve the implementation of the initialize method of classification)

summary

  1. Called when the initialize message received first class, that is objc_msgSend(), by its very nature is objc_msgSenda method call;
  2. In the class initialization, initialize priority call parent class, then call initialize this class;
  3. If this class does not implement initialize, and initialize the parent class implements, then this class initialization initialize method to call and inherits the parent class, through the
    superclass to find the parent class, initialize method means that the parent may be called multiple times ;
  4. Initialize method inherited from the parent class of class prior to the present method implementation will initialize coverage;
  5. When rewriting initialize method, no need to call [super initialize]the method, because of its internal look up automatically performed recursively parent initialize method;
  6. Initialize method of classification will take precedence, the initialize method in this class will not be called, the reason is obj_msgSenda method mechanism;

Other characteristics with respect to the initialize:
When there are multiple classification implements initialize method, only the execution of the last one of the categories (a final classification refers to an arrangement in the order of most against the Compile Sources);


Postscript:
 About initialize method of the class load and initialize it first wrote here. In finishing the writing process, I also found a need to have a lot of knowledge to be improved, for example: each class, load classification method is when and how to load can be loaded into the load list, dyld mirror image of the dynamic link library operational processes files. Follow-up will continue to add, if inaccuracies occur article also requested a lot of guidance.


This article was first published in Jane book: I was just writing out the code blog and automatically synchronized to Tencent cloud: I just write out iOS blog

Reproduced in: https: //www.jianshu.com/p/0dac269f2055

Guess you like

Origin blog.csdn.net/weixin_34026484/article/details/91183147