您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

iOS的第一个基本原则—dyld和objc之间的关系 <源码分享>

  • 时间:2022-08-13 02:22 编辑: 来源: 阅读:304
  • 扫一扫,手机访问
摘要:iOS的第一个基本原则—dyld和objc之间的关系 <源码分享>
作者:我是小菜。参考链接:https://juejin.im/post/6884147035172405256.前言在dyld加载的过程中,我们知道会调用_objc_init方法。那么我们在_objc_init方法中做了什么呢?我们来探索一下。 _objc_init方法_objc_init方法实现void _ objc _ init(void){ static bool initialized = false;if(初始化)返回;初始化=真;// fixme延迟初始化,直到找到使用objc的映像?environ _ init();TLS _ init();static_init()。runtime _ init();exception_init()。cache _ init();_ imp _ implementationWithBlock _ init();_ dyld _ objc _ notify _ register(& amp;map_images,load_images,unmap _ image);# if _ _ objc 2 _ _ didCallDyldNotifyRegister = true;#endif}从_objc_init的实现来分析这个方法主要做什么:environ_init()。这个方法主要读取运行时环境变量。我们可以通过设置DYLD_PRINT_STATISTICS = YES,将APP启动前的时间打印到main()函数,然后就可以优化APP启动了。 请参考博客iOS-底层原理16:16:dyld与objc的关联中environ_init()的细节。tls_init()主要用于线程键的绑定,比如每个线程的数据的析构函数。 void TLS _ init(void){ # if SUPPORT _ DIRECT _ THREAD _ KEYS pthread _ KEY _ init _ NP(TLS _ DIRECT _ KEY,& amp_ objc _ pthread _ destroy specific);# else _ objc _ pthread _ key = TLS _ create(& amp;_ objc _ pthread _ destroy specific);#endif}static_init()主要是C++静态构造函数static void static _ init(){ size _ tcount;auto inits = getlibobjcinitializer(& amp;_mh_dylib_header。计数);for(size _ t I = 0;我& lt数数;i++){ inits[I]();}}runtime_init()主要是运行时的初始化,主要分为两部分:类初始化和类表初始化void runtime _ init(void){ objc::unattached categories . init(32);objc::allocated classes . init();}初始化libobjc的异常处理系统。*由map_images()调用。* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */void exception _ init(void){ old _ termin ate = STD::set _ termin ate(& amp;_ objc _ termin ate);}cache_init()主要是缓存初始化void cache _ init(){ # if have _ task _ restart able _ ranges mach _ msg _ type _ number _ tcount = 0;kern _ return _ t krwhile(objc _ restartableRanges[count])。location){ count++;} kr = task _ restartable _ ranges _ register(mach _ task _ self(),objc_restartableRanges,count);if (kr == KERN_SUCCESS)返回;_ objc _ fatal(" task _ restart able _ ranges _ register失败(结果0x%x: %s)",kr,mach _ error _ string(kr));# endif//have _ task _ restartable _ ranges } _ imp _ implementationWithBlock _ init()主要用于启动机制回调//一切都是惰性初始化的,但是对于某些进程我们急切地加载//trampolines dylib . void _ imp _ implementationWithBlock _ init(void){ # if TARGET _ OS _ OSX//急切地加载libobjc-trampolines.dylib。一些//程序(最明显的是旧版// embedded Chromium使用的QtWebEngineProcess)启用了高度限制性的沙盒配置文件,该配置文件//会阻止对该dylib的访问。如果有任何东西调用// imp_implementationWithBlock(就像AppKit已经开始做的那样),那么我们就会//试图加载它时崩溃。在沙箱//配置文件启用并阻止它之前,在这里加载它会设置它。// //这修复了EA Origin(rdar://problem/50813789)//和Steam(rdar://problem/55286131)if(_ _ progname & amp;& amp(strcmp(__progname," QtWebEngineProcess ")= = 0 | | strcmp(_ _ progname," Steam Helper") == 0)) { Trampolines。initialize();}#endif}dyld关联objc _ dyld _ objc _ notify _ register(& Map _ images,load _ images,unmap _ image)主要是dyld注册的实际代码实现:void _ dyld _ objc _ notify _ register(_ dyld _ objc _ notify _ mapped,_dyld_objc_notify_init,_ dyld _ objc _ notify _ unmapped){ dyld::registerobjc notifiers(mapped,init,unmapped);}从上面中间我们可以看到,mapped的意思是map_imagesinit的意思是load _ imagesunmapped的意思是unmap_imagemap_images()函数分析/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * map _ images *处理dyld正在映射的给定图像。*在获取特定于ABI的锁后,调用与ABI无关的代码。**锁定:write-locks runtime lock * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */void map _ images(unsigned count,const char * const paths[],const struct mach _ header * const MHD RS[]){ mutex _ locker _ t lock(runtime lock);返回map_images_nolock(计数,路径,mhdrs);}从map_images函数中我们发现map_images_nolock函数是重点,我们进入map_images_nolock函数map_images_nolock。我们来看看代码实现。从截图中我们可以看出_read_images是我们应该重点关注的方法。_read_images函数分析可以第一时间加载并修复@selector在预编译时的混淆问题。错误类解决方案,readClass读出的类的信息重置映射镜像消息。如果解决方案类中有协议,则读取加载分类的协议映射协议。注意分类方案主要是通过load_categories_nolock来解决的。我们进入load_categories_nolock函数静态void load _ categories _ no lock(header _ info * hi){ boolhaskclassproperties = hi->;info()-& gt;hasCategoryClassProperties();size _ t countauto process catlist =[& amp;](category _ t * const * cat list){ for(无符号I = 0;我& lt数数;i++){ category _ t * cat = cat list[I];class cls = remap class(cat-& gt;cls);locstamped_category_t lc{cat,hi };如果(!cls) { //缺少类别的目标类(可能是弱链接的)。//忽略类别。if(print connecting){ _ objc _ inform(" CLASS:忽略类别\?\?\?(%s) %p带有" "缺少弱链接目标类",目录-& gt;姓名,猫);}继续;} //处理此类别。if(cls-& gt;isStubClass()) { //存根类永远不会实现。存根类//直到被//初始化时才知道它们的元类,所以我们必须将带有//类方法或属性的类别添加到存根本身。// methodizeClass()将找到它们并将它们适当地添加到//元类中。如果(猫->;instanceMethods || cat->协议||猫->;实例属性||目录-& gt;class methods | | cat-& gt;协议| |(hasClassProperties & amp;& amp猫->;_ class properties)){ objc::unattached categories . addfor class(LC,cls);} } else { //首先,向其目标类注册类别。//然后,如果//实现了该类,则重建该类的方法列表(etc)。如果(猫->;instanceMethods || cat->协议||猫->;instance properties){ if(cls-& gt;is realized()){ attach categories(cls,& amplc,1,ATTACH _ EXISTING);} else { objc::unattached categories . addfor class(LC,cls);} } if(cat-& gt;class methods | | cat-& gt;协议| |(hasClassProperties & amp;& amp猫->;_ class properties)){ if(cls-& gt;ISA()-& gt;is realized()){ attach categories(cls-& gt;ISA(),& amplc,1,ATTACH _ EXISTING | ATTACH _ METACLASS);} else { objc::unattached categories . addfor class(LC,cls-& gt;ISA());} } } } };processCatlist(_ getobjc 2 categorylist(hi,& ampcount));processCatlist(_ getobjc 2 categorylist 2(hi,& ampcount));}从load_categories_nolock函数的实现可以看出,这个函数链接了类、实例方法、协议、属性、类方法等。再一次。 解决懒加载类的问题解决未使用类dyld与objc的关联摘要dyld_start调用_objc_init进行初始化,而_dyld_objc_notify_register函数由dyld在_objc_init中调用。传入两个参数map_images和load_images来求解map_images。通过map_images_nolock函数调用_read_images函数,求解类信息、属性、协议、分类等。在_read_images函数中。一切准备就绪后,再次返回dyld_start。此时,dyld与objc相关联。信息推荐:如果你正在跳槽或者准备跳槽,不妨动动手脚,增加我们的交流群1012951431,获取一个大厂的详细面试信息,为你的跳槽增加一份保障。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【域名/主机/服务器|】qq邮箱提醒在哪里打开(2024-06-04 18:58)
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部