上一篇咱们根究到了readClass
函数,仅仅对函数姓名进行了赋值,并没有对ro
和rw
进行操作,本篇咱们就持续根究_read_images
函数剩余的调用。
realizeClass的引入
由于咱们根究的目的是类
的加载,变量的界说咱们先疏忽protocol
和cat实例化数组egorieappointments
的当地。为了调试代码,咱们首先仍是先创立一个JSPerson
类:
@interface JSPerson : NSObject
@property (nonatomic, strong) NSString *nickName;
- (vo实例化一个类id)say1;
- (void)say2;
+ (void)sayHappy;
@end
#import "JSPerson.h"
@源码编辑器implementation JSPe实例化类rson
- (void)实例化目标是什么意思say1{
NSLog(@"JSPerson say : %s",变量是什么意思__func__);
}
- (void)say2{
NSLog(@"JSPerson say : %s",__func__);
}
+ (void)load{
NSLog(@"load");
}
+ (void)sayHappy{
NSLog(@"JSPerson say : %s"实例化目标是什么意思,__func__);
}
@end
接下来咱们持续看_read_images
函数,发现和类相关的当地有两个当地,realize non-lazy classes
和realize futureSwift classes
,咱们在swift代码是什么意思两段代码中参加咱们调试的代码,为了调查咱们自界说类的加载情况:
// R实例化servlet类异常ealize non-lazy classes (for +load methods and static instances)
for (EACH_HEADER) {
cswiftcode代码查询lassref_t const *classlist = hi->nlclslist(&count);
for (i = 0; i < count; i++) {
Class cls = remapClass(classlist[i]);
if (!clapproachs) continue;
///调试代码 确定是咱们自界说的类
const char *mangledName = cls->nonlaz源码本钱yMan实例化一个类gledName();
const char *customerClassName = "JSPerson";
if (strcmp(mangled实例化目标是什么意思Name, customerClassName) == 0) {
//打印类名
printf("%s -: no源码下载n-laz源码是什么意思y classes要研讨的类: - %sn",__func_变量是什么意思_,mangledName);
}
addClassTableEntry(cls);
if (cls->isSwiftStable()变量名的命名规矩) {
if源码 (cls->swiftMetadataInitializer()) {
_objc_fatal("Swift class %s with a metadata init源码年代ializer "
"is not al实例化类lowed to be non变量是什么意思-lazy",
cls-源码之家>nameForLogging());
}
// fixm源码年代e alswiftlyso disallow relocatable classes
// We canappreciate't disallswiftlyow all Swift classes because of
// classes like Swift.__EmptyArrayStorage
}
realizeClas实例化类sWithoutSwift(cls, niswifterl);
}
}
ts.log("IMAGE TIMES: realize non-lazy c源码下载lasses");
// Realize newly-resolved future classes, i变量的界说n case CF manipulates them
if (resolvedFutureClasses) {
for (i = 0; i < rapp下载esolvedFutureClassCount; i++) {
Class cls变量的界说 = resolvedFutureClasses[i];
if (cls->isSwiftStable()) {
_objc_fatal("Swiftappetite clswift国际结算体系ass is not allowed to be future");
}
///调试代码 确定是咱们自界说的类
const char *mangledName = cls源码是什么意思->nonlazyMangledNswiftcode是什么意思中文ame();
const char *customerClassName = "JSPerson";
if (strcmp(mswift怎样读angledName, customerClassName) == 0) {
//打印类名
printf("%s -: realize future classes要研讨的类: - %sn",__func__,mangledName);
}
realizeClassWit实例化类houtSwift(cls, nil);
cls->setInstancesSwiftRequireRawIsaRecursively(false/*inherited*/);
}
free(resolvedFutureClasses);
}
ts.log("IMAGE TIMES: realize future classes");
在两行printf
的当地打断变量泵点,作业源码程序,看是否实施到断点方位。发现打印了_read_images -:源码之家 non-lazy classes要研讨的类: - JSPerson
,代码实施到了non-lazy classes
,里面类加载的中心代码在realizeClassWithoutSwift
函数,咱们持续根究realizeClassWithoutSwift
函数。
realizeClassWithoutSwift剖析
操作之前的ro
咱们从上到下顺次阅读代码,定位到auto ro = (const class_ro_t )cls->data();
,由于ro
是clean Memory
里的数据咱们比较活络,咱们在图示方位打断点:
运用LLDB
调试程序,检查ro
里的信息:
(lldb) p ro变量泵
(const class实例化是什么意思_ro_t *) $0 = 0x00000001000080c0
(lldb) p *$0
(const class_ro_t) $1 =实例化目标 {
flags = 0
instanceStaapp是什么意思rt = 8
insta实例化目标的关键字nceSize = 16
reserved = 0
= {
ivarLayout = 0x0000000000000000
nonMetaclass = nil
}
name = {
std::__1::atomicswiftcode代码查询<const char *> = "JSPerson" {
Value = 0x0000000100003db0 "JSPerson"源码下载
}
}
b源码a实例化需求seMethodList = 0x0000000100008108
baseProtoc源码怎样做成app软件ols = 0x0000000000000000
ivars = 0x0000000100008170
weakIvarswift怎样读Layout = 0x0000000000000000
baseProperties = 0x变量与函数0000000100008198
_swiftMetadataInitializer_NEVER_USE = {}
}
(lldb) p $1.baseMethodList
(void *constapple) $2 =变量 0x0000000100008108
(lldb) p *$2变量名的命名规矩
(lldb)
经过打印咱们发现此时ro
里的baseMethodList
为空,现在还不清楚什么时分赋值的,咱们application持续根究。
rw的赋approach值
接下来便是对rw
的赋值app是什么意思,留意rw
是dirty Memory
if (ro->flags & RO_FUTURE) {
// This was a future class. rw data is already allo源码交易平台排行cated.
rw = cls->data();
ro = cls->data()-&gswift代码t;ro();
ASSERT(!is变量名的命名规矩Meta);
cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
} else {
// Normal class. Allocat变量的界说e writeable class data.
rw = objc::zalloc<class_rw_t>();
rw->set_ro(ro);
rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
cls->变量之间的联系;setData(rw);
}
isa和su实例化目标有几种办法perClass赋值
后swiftly边的代码便是对isa
和suswift怎样读perClass
的赋值:
supercls = realizeClassWithoutSwift(remapClass(clswiftcode是什么意思中文s->getSuperclass()), nilapplication);
metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil源码本钱);
#if SUPPORT_NONPOINTER_ISA
if (isMeta) {
// Metaclasses do not nswift代码eed any features from non pointer ISA
// This allows f变量名or a faspath for classes iswift代码n objc_retain/objc_release.
///元类 不是nswiftlyon pointer ISA
cls->setInstancesRequireRawIsa();
} el实例化一个类se {
// Disable non-poinswift代码ter isa for some classes and/or platfo源码之家rms.
// Setappstore instancesRequir变量名eRawIsa.
bool instancesRequireR变量名awIsa = cls->instancesRequireRawIsa();
bool rawIsaIsInheriteappstored = false;
static bool hackedDispatch = false;
if (DisableNonpointerIsa) {
//假设咱们设置变量不运用 non pointer ISA 也会是纯的isa
// Non-pointer isa disabled变量的指针其意义是指该变量的 by eapproachnvironment or app SDK version
instancesRequireRawIsa = true;
}
else if (!hackedDispatch && 0 == strcmp(ro-swift体系>getName(), "OS_object"))
{
// hack for libdis变量patch et al - isaappreciate also acts as vtable pointer
hackedDispaAPPtch = true;
instancesRequireRawIsa = true;
}
else if (suappstorepercls && supercapp是什么意思ls->getSuperclass() &&
su实例化类percls-&g变量名t;instancesRequ实例化目标的关键字ireRawIsa())
{
// This is also propagated by addSubclass()
// but nonpointer isa setup needs it earlier.
// Special case: instancesRequireRawIsa does not propagate
// from root class to root metaclass
instappleancesRequireRawIsa = true;
rawIsaIsInherited = true;
}
if (instancesRequireRawIsa) {
cls->setInstancesappleRequappreciateireRawIsaRecursively(rawIsaIsInherited);
}
}
// SUPPORT_NONPOINTER源码之家_ISA
#endif
// Updat源码编辑器e superclass answift怎样读d metaclass in case of rapp下载emapping
cls->setSuperclass(supe实例化需求rcls);
cls->swiftcode是什么意思中文initClassIsa(metacls);
在realizeClassWithoutSwift
函数最终会调用methodizeClas实例化目标有几种办法s变量之间的联系
,咱们下一小节根究methodizeClass
。
methodizeClass剖析
methodizeClass
断章取义便是源码怎样做成app软件对办法的处理。
static void metho变量dizeClass(Class cls, Cl源码年代坑人ass previously)
{
runtimeLock.assertLocked();
bool isMeta = cls->isMetaClass();
auto rw = cls->源码交易平台排行;data();
auto ro = rw-&gappetitet;ro();
auto rwe = rw->ext()源码下载;
// Methodizing for the first time
if (PrintConnectin实例化一个类g) {
_objc_inform("CLASS: methodizing class '%s' %s",
cls->nameForLog变量是什么意思ging(),swift代码 isMeta ? "(meta)" : "");
}
///调试代码 确定是咱们自界说的类
consSwiftt char *mangledName =swiftkey cls->nonlazyMangledName(swiftcode是什么意思中文);
const char *customerClassName = "JSP变量泵ersonapp是什么意思";
if (strcmp(mangledName, custo源码交易网站源码merClassName) == 0) {
//打源码之家印类名
if (!isMeta) {
prin源码本钱tf("%s -: non-lazy classes要研讨的类: - %sn"源码年代坑人,app是什么意思__func__,mangledName);
}
}
// Install methods and properties that the class implements itself.
//取出办法列表
method_list_t *list = ro->baseMethods();
if (list变量名) {源码之家
prepareMethodLappreciateists(cls, &list, 1, YES, isBundleClass(cls), nullptr);
if (rwe) rwe-&g变量是什么意思t;methods变量类型有哪些.attachLists(变量类型有哪些&aapplemp;list, 1);
}
property_list_t *proplist = ro-&g源码怎样做成app软件t;baseProperties;
if (r源码编辑器we && proplist) {
rwe->propapplicationerties.变量的指针其意义是指该变量的attachLiSwiftsts(&proplist, 1);
}
protocol_list_t *protolist = ro->baseProtocols;
if (rwe && protolist) {
rw实例化一个类e->pro源码交易平台排行tocols.attachLists(&protolist, 1);
}
// Root classes get bonus method implementations if theyappreciate don't have
// them already. These apply before category replacements.
if (cls->isRootMetaclass()) {
// roSwiftot metaclass
addMethod(cls, @selector(initialize), (IMP)&objc_noop_imp, "", NO);
}
// Attaswiftcode代码查询ch categories.
if (源码编辑器previously) {
if (isMeta) {
objc::unattachedCategories.attachToClass(cls, previously,
ATTACH_METACLASS);
} else {
// When a class relocates, categories with class methods
// may be registered on the class itself rather than on
// the metaclass. Tell attachToClass to look for those.
objc::unattachedCategories.attachToCl实例化目标的关键字ass(cls, pappearreviously,
ATTACH_CLAswift怎样读SS_AND变量名_METACLASS)实例化需求;
}
}
objc::unattachedCat源码之家egories.attachToClass(cls, cls,
isMeta ? ATTACH_METACLASS : ATTACH_appearCLASS);
#if DEBUG
// Debug: sanity-check all SELs; log method list contents
for (coswift国际结算体系nst auto& me实例化目标的关键字th : rw->me源码thods()) {
if (源码年代坑人PrintConnecting) {
_objc_inform("METHOD实例化类 %APPc[%s %s]", isMeta ? '+' : '-',
cls->nameForLogging(), sel_getName(m变量类型有哪些eth.name()));
}
ASSERT(sel_swifterregisterName(sel_getNappleame(meth.name())) == meth.name(源码编辑器));
}
#endif
}
断点进入图示方位,此时办法列表仍是不能源码是什么意思打印
prepareMethodLists
咱们持续根究,后边实施prepareMethodLisswiftlyts
函数。
static void
prepareMethodLists(Class cls, method_list_t **addedLists, int addedCount,
bool baseMethods, bool methodsFromBundle, const char *w源码编辑器hy)
{
runtimeLock.assertLo变量的指针其意义是指该变量的cked();
if (addedCount == 0) return;
// There exist RR/AWZ/Core special cases fappointmentor some class's base methods.
/变量之间的联系/ But this code should never need to scan base methods for RR/AWZ/Core:
// default RR/AWZ/Core cannot be set before setInitialized().
// Therefore源码本钱 we needAPP not handle any special case源码年代坑人s here.
if (baseMethods) {
ASSERT(cls->hasCustomAWZ() && cls->hasCuswifters变量值tomRR() && cls->hasCustomCore());
} else if (cls->cache.isConstant实例化是什么意思OptimizedCac变量名he()) {
cls-&swiftcode是什么意思中文gt;setDisallowPreoptCachesRecursively(why);
} else if (cls->allowsPreoptInlinedSels()) {
#if CO变量NFIG_USE_PREOPT_CACHES
SEL *sels = (SEL *)objc_opt_offsets[OBJC_OPT_INLINED_METHODS_START];
SEL *sels_end = (SEL *)objc_opt_offsets[OB变量JC_OPT_INLINED_MapproachETHODS_END];
if (method_list变量的指针其意义是指该变量的s_contains_any(addedLists, addedL源码ists + addedCount, sels, sels_end - sels)) {实例化数组
cls->setDisallo变量泵wPreoptInlinedSelsRecursively(why);
}
#endif
}
// Add method lists to array.
// Reallocate un-fixed method lists.
// Tapp下载he new methods are PREPENDED to the method list array.
for (int i = 0; i < addedCount; i++) {
method_list_t *mlist = addedLists[i];
ASSERT(mlappearist);
// Fixup selectors if necessary
if (!mlist->isFixedUp()) {
//中心代码
fixupMethodList(mlist, methodsFswiftlyromBundle, true/*sort*/);
}
}
// If the class is initialized,源码年代坑人 then scan for method implementations
// tracked by the class's flags. If it's not initialized yet,
// then objc_class::setInitialized() will take car源码是什么意思e of it.
if (cls->isInitialized()) {
objc::AWZScanner::scanAddedMe变量thodLists(cls, addedL变量类型有哪些ists, addedCount);
objc::appleRRScanner::scanAddedMethodLists(cls, add实例化目标有几种办法edLists, addedCount);
objc::CorswiftereScanner::sc变量泵anAddedMetho源码年代坑人dLists(cls, add实例化目标是什么意思edLists, addedCount);
}
}
中心调用是fixupMethodList
函数。
fapp是什么意思ixupMeappstorethodList
static void
fixupMethodLisappreciatet(method_list_t *mlist, bo源码之家ol bu实例化目标有几种办法ndleCopy, bool sort)
{
runtimeLock.assertLocked();
ASSERT(!mlist->isFixedUp());
// fixme lock less in attachMethodLists ?
// dyld3 may have already uniqued, but not sorted, the list
if (!mlist->isUniqued()) {
mutex_locker_t lock(selLock);
// Unique selectors in list.
for (auto&源码年代坑人; meth : *mlist) {
const char *name = sel_cna源码之家me(meth.name());
meth.setNa变量名的命名规矩me(sel_registerNameNoLock(name, bundleCopy));
}
}
// Sort by sel变量名的命名规矩ector address.
/源码交易网站源码/ Don't try to sort small lists, as they're immutable.
// Don't try to sort big lists of nonstandard size, as stabswiftcode是什么意思中文le_sort
// won'tapproach copy the entries properly源码之家.
if (sort &&appointment !mlist->isSmallswift体系List() &&变量之间的联系 mlist->entsize() == method_t::bigSize) {
method_t::So变量rtBySELAddress sorter;
std::stable_sort(&mlist->begin()->bi实例化一个类g(), &mlist->end()->big(), sor变量之间的联系ter);
}
// Mark method list as uniqued and sorted.
// Can't mark small lists, since they're immutableAPP.
if (!mlist->实例化类;isSmallList()) {
mlist-&源码是什么意思gt;setFixedUp();
}
}
中心的代码源码编辑器是stable_sort
,咱们别离打印排序前后办法列表,如图示
留意:这儿一定要先在realizeClassWithoutSwift
判别好是咱们要研讨的JSPerson
类,然后再看打印效果,否则体系类也会有许多打印,影响咱们剖析。
me实例化thodizeClass -: non-lazy classes要研讨的类: - JSPerson
****************sort之前 : say1 - 0x100003dda
sort之前 : say2 - 0x100003ddf
sort之前 : nickNamappointmente - 0x7fff73fb8a1c
sort之前 : setNickName: - 0x7fff73fb8362
****************sort之后 : say1 - 0x1swift体系00003dda
sort之后实例化需求 : say2 - 0x100003ddf
sort之后 : setNickName: - 0x7fff73fb8362
sort之后 : nickName - 0x7fff73fb8a1c
经过上面打印效果:
- 排序前:
say1appointment - 0x100003dda
、say2 - 0x100003ddf
、nickName - 0x7fff73fb8a1c
、setNickName: - 0x7fff73fapp下载b8362
- 排序后:
say1 - 0x100003ddaswift代码是什么意思
、say2 - 0x100003ddf
、setNickName: - 0x7fff73fb8362
、nickName - 0x7fff73fb8a1c
- 排序是依实例化目标是什么意思据地址由低到高排序的。
小结
到现在为止,类的加载流程是:_read_im实例化数组ages
->re实例化一个类alswift代码是什么意思izeClassWithoutSwiftapproach
->methodizeClass
->prepareMethodLists
->fixupMethodL实例化目标ist
。
懒加载类和非懒加载类
咱们前面根究的其实都是非懒加载的类
,懒加载类
和非懒加载的类
的差异便是是否完成了load
办法。
非懒加载
经过上面的剖析,咱们现已很清楚了,是在_objc_源码交易网站源码init
办法里加载变量名的,也便是程序发起的时分APP。这也便是为什么变量之间的联系load
办法过多,会影响咱们使用的发起速度
。
懒加载类
由于非懒加载类
效率低,会影响咱们的发起速度,那懒加载类
是什么时分加载的呢?咱们删掉JSPerson
类的load
办法,然后在main
函数中实例化一个JSPerson
实例
in实例化servlet类异常t main(int arg源码编辑器c, const charapplication * argv[]源码年代坑人) {
@autorelea变量值sepool {
JSPerson *p = [JSPerson alloc];
[p say1]app下载;
NSLog(@"Hello, World!");
}
return 0;
}
咱们首先在main
办法里增加断点,实施程序。走到main
函数之swift代码是什么意思后,然后再在realizeClassWithoutSwift
增加断点:
断点走进来之后咱们bt
打印调用栈信息:
发现调用是从lookUpImpOrForward
开端。
所以咱们的结论是懒加载的类
是在第一次被运用的时分加载的。
总结
-
非懒加载类:程序作业时加载,
_read_images
->realizeClassWithoutSwift
->metho实例化数组dizeClass
->prepareMethodLists
->fixupMethodList
。 -
懒加载类:第一次运用时加载,
lookUpImpOrForward
->realizeClassWithoutSwift
->变量与函数methodizeClass
->prepareMethodLists
->fixupMethodList
咱们开发中经常会写
分类
,它是什么时分加载的及加载的流程,咱们下一篇再根究。