preface
On an iOS underlying principle that article class loading principle, finally when it comes to readClass function through, still don’t see the ro and related operations of rw, today just readClass function to continue to explore.
The preparatory work
- Objc4-818.2 – the source code
I. Introduction of realizeClassWithoutSwift
Take a look at the SSLPerson class:
@interface SSLPerson : NSObjec
- (void)say1;
- (void)say2;
- (void)say3;
@end
@implementation SSLPerson
+ (void)load
{
NSLog(@"load");
}
- (void)say1
{
NSLog(@"func-----say1");
}
- (void)say2
{
NSLog(@"func-----say2");
}
- (void)say3
{
NSLog(@"func-----say3");
}
@end
Copy the code
Now that we have analyzed the _read_images function to execute readClass, let’s go further and add the conditional control code for the SSLPerson class to the source code:
Run the program to see if you can enter the breakpoint:
- You can see that the breakpoint entered successfully
cls
It’s oursSSLPerson
Class. inrealizeClassWithoutSwift
The break point at the function, and then the break point entersrealizeClassWithoutSwift
.
Second, realizeClassWithoutSwift analysis
The ro baseMethods
Breakpoint to enter realizeClassWithoutSwift:
Debug via LLDB print:
- As you can see by printing,
ro
The list of methods in this time already has values, respectivelysay4
,say1
,say2
,say3
“, so let’s move on.
Rw and RO operations
- This code, create
rw
That will bero
The value is assigned torw
And thenrw
Assigned to the classbits
And keep going.
Isa related processing
- If it is
MetaClass
To callsetInstancesRequireRawIsa
Function. - not
MetaClass
If this parameter is setDisableNonpointerIsa
Value of, will also be carried outinstancesRequireRawIsa
Related treatment, last articleUnderlying principles of iOS: class loading principlesWe have toDisableNonpointerIsa
The environment variable has been operated. Procedure
SetSuperclass, initClassIsa
Keep going:
- This is a recursive setting
superClass
Of the inheritance chain, andisa
The location chain of.
- If I do a little bit more Settings, I’ll get to
methodizeClass
Function, we’re going to go intomethodizeClass
Explore, as shown here2751
Line.
Three, methodizeClass analysis
Break point to methodizeClass:
- Here by
baseMethods()
Gets a list of methods, if any, and calls themprepareMethodLists
Functions process methods.
prepareMethodLists
Enter the prepareMethodLists:
static void prepareMethodLists(Class cls, method_list_t **addedLists, int addedCount, bool baseMethods, bool methodsFromBundle, const char *why) { // Add method lists to array. // Reallocate un-fixed method lists. // The new methods are PREPENDED to the method list array. for (int i = 0; i < addedCount; i++) { method_list_t *mlist = addedLists[i]; ASSERT(mlist); // Fixup selectors if necessary if (! mlist->isFixedUp()) { fixupMethodList(mlist, methodsFromBundle, true/*sort*/); }}}Copy the code
fixupMethodList
Click to go to fixupMethodList:
static void
fixupMethodList(method_list_t *mlist, bool bundleCopy, bool sort)
{
...
// Sort by selector address.
// Don't try to sort small lists, as they're immutable.
// Don't try to sort big lists of nonstandard size, as stable_sort
// won't copy the entries properly.
if (sort && !mlist->isSmallList() && mlist->entsize() == method_t::bigSize) {
method_t::SortBySELAddress sorter;
std::stable_sort(&mlist->begin()->big(), &mlist->end()->big(), sorter);
}
...
}
Copy the code
- Look at the code,
SortBySELAddress
Is in accordance with theSEL
Address sort. We are inOC Principle Exploration: a slow lookup process for methodsIn the saidSlow search process
In theBinary search
I’m using this sorted list right here, and I’m going to verify it.
Add code before and after the sort code to print the method name and address:
To view the print:
- The method print order before sorting is
say4
,say1
,say2
,say3
. - After sorting the method print order is
say1
,say4
,say2
,say3
, the address size is0x100003f81 < 0x100003f8b < 0x100003f90 < 0x100003f95
Yes, it is in order from smallest to largest.
Lazy-loaded and non-lazy-loaded classes
To summarize the above flow: Read_images -> realizeClassWithoutSwift -> methodizeClass -> prepareMethodLists -> fixupMethodList.
Non-lazily loaded classes
Going back to the first part of the article, the _read_images function executes readClass, which is the following code:
- We will be
SSLPerson
In the classload
Method, run the program again, found here the breakpoint can not enter. - That’s where it comes in
Lazy loading class
withNon-lazily loaded classes
, if you have+ load
Method will do a non-lazy load, which will happen when the program startsro
,rw
,The sorting
And so on a series of operations, very time-consuming.
Lazy loading class
Non-lazy loading of classes is very inefficient. If all classes are non-lazy loading, it will be very, very time-consuming. Therefore, Apple adopts on-demand loading, that is, lazy loading of classes and loading them when they are needed.
When is the non-lazily loaded class loaded? Through the above process, we can know that the class loading will do RW, RO, sort and other operations, namely realizeClassWithoutSwift, so I will explore this as the entry point.
Add a method call to the SSLPerson class in main.m:
int main(int argc, const char * argv[]) {
@autoreleasepool {
SSLPerson *person = [SSLPerson alloc];
}
return 0;
}
Copy the code
Add a breakpoint to the SSLPerson class in realizeClassWithoutSwift and run the program:
- I can successfully break it here, and then
bt
Print the stack.
- To see the
lookUpImpOrForward
Function, which we are familiar with, is called during a slow lookup process, that is, when the class is first usedLazy loading class
.
The next article will be the exploration of classification loading, there are questions can be more communication in the comment area, click a like to support it!! π π π