iOS内存管理——autorelease方法解析
来源:互联网 发布:中文域名续费诈骗 编辑:程序博客网 时间:2024/06/01 07:45
iOS内存管理——autorelease
- autorelease 自动释放
- 注意:autorelease和ARC 是完全不同的两个东西,没有任何联系。
autorelease和ARC
- autorelease的内存管理方式是在autoreleasePool释放的时候对其中持有的对象依次进行release操作,这样做有个隐患就是如果autoreleasePool迟迟不能被释放,则会有大量的对象在内存中,会有内存峰值的问题存在。
- ARC则是在对象不被使用的时候释放,它的管理规则我们会在后边的文章详细讨论,这里只需要知道它们是完全不同的两个东西即可。
aurorelease的工作方式
{ 声明变量。。}变量释放
在c语言中我们会说局部变量超出了作用域而被释放,”{}”的范围即是它的作用域。
在autoreleasePool的工作方式中我们也有作用域的概念存在,只不过不是用”{}”来划分的,而是NSAutoreleasePool。步骤如下:
1,生成并持有NSAutoreleasePool对象; 2,调用已分配对象的autorelease实例方法; 3,废弃NSAutoreleasePool对象;
代码如下:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; id obj = [[NSObject alloc] init]; [obj autorelease]; [pool drain];
autorelease发生内存峰值的情况
在我们加载大量的图片时会有这个风险,eg:
for(int i=0; i<100; i++) { 1,创建图片 2,产生大量的autorelease对象 3,在没有使用NSAutoreleasePool控制作用域的情况下没有及时的释放2中创建对象。 4,内存峰值上升}
解决方法:
for(int i=0; i<100; i++) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 1,创建图片 2,产生大量的autorelease对象 //废弃pool,其中的autorelease对象会调用release方法。 [pool drain];}
autorelease对象产生峰值的原因 autorelease对象到底什么时候释放 引用自(这个博客)[http://www.jianshu.com/p/494481d59278]
主线程有个事件循环。每次有事件的时候,由cocoa框架调用我们写的代码,再回到cocoa框架。NSAutoreleasePool其实是由cocoa框架管理的,当出了我们写的代码,回到框架的时候,放入NSAutoreleasePool的对象就会由框架调用release, 这样就保证跑我们代码的时候,对象是会存在的,出了我们的代码,对象也能够正常地被释放。
比如
系统代码(事件激发)
funA()
funB()
funC()
funD()
系统代码(等待事件)
在funA, funB, funC, funD中,无论调用多少层,也是用户写的代码。autorelease的对象还是存在的。下一次事件激发的时候,上一次事件的对象是不存在的,因为已经被系统框架调用release回收了。除非你自己调用了retain, 自己调用了一次retain, 就应该自己来调用一次release, 这样也没有违背上面说的原则。
自动释放池的缺点:它延缓了对象的释放,在有大量自动释放的对象时,会占用大量内存资源。因此,你需要避免将大量对象自动释放。并且,在以下两种情况下,你需要手动建立并手动销毁掉自动释放池:
1.当你在主线程外开启其它线程时:系统只会在主线程中自动生成并销毁掉自动释放池。(runloop未开启)
2.当你在短时间内制造了大量自动释放对象时:及时地销毁有助于有效利用iPad上有限地内存资源
iOS的运行时是由一个一个runloop组成的,每个runloop都会执行下图的一些步骤:
可以看到,每个runloop中都创建一个Autorelease Pool,并在runloop的末尾进行释放,
所以,一般情况下,每个接受autorelease消息的对象,都会在下个runloop开始前被释放。也就是说,在一段同步的代码中执行过程中,生成的对象接受autorelease消息后,一般是不会在代码段执行完成前释放的。
简洁来说:
autorelease对象放在autoreleasePool中。
autoreleasePool销毁时autorelease对象才会被释放。
autoreleasePool默认是在NSRunloop的最后阶段自动被执行,也可以手动强制的调用销毁方法。
所以autorelease对象的释放时间是在NSRunLoop的最后阶段自动释放或者手动强制释放
autorelease 实现
在objc4库的runtime/objc-arr.mm中
- objc4/runtime/objc-arr.mm class Auto autoreleasePoolPage
class AutoreleasePoolPage{ static inline void *push() { 生成或者持有NSAutoreleasePool对象 } static inline void *pop() { 废弃NSAutoreleasePool对象; releaseAll() } static inline id autorelease(id obj) { 相当于往pool中添加对象 1,取得最近的pool对象 2,autoreleasePoolPage->add(obj) } id *add(id obj) { 将对象追加到内部数组中 } void releaseAll() { 调用内部数组中对象的release实例方法 }};void *objc_autoreleasePoolPush(void){ return AutoreleasePoolPage::push();}void *objc_autoreleasePoolPop(void *ctxt){ AutoreleasePoolPage::pop(ctxt);}id *objc_autorelease(id obj) { return AutoreleasePoolPage::autorelease(obj);}
通过如上的代码解析,我们之前看到的autoreleasePool的工作方式可以进一步解释为:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //objc_autoreleasePoolPush(); id obj = [[NSObject alloc] init]; [obj autorelease]; //objc_autorelease(obj); [pool drain]; //objc_autoreleasePoolPop(pool);
如果对NSAutoreleasePool对象使用autorelease方法会发生什么
会发生异常
通常在Foundation框架中,无论哪个实例对象调用autorelease方法都是调用NSObject类的autorelease实例方法。
但是NSAutoreleasePool类对autorelease方法进行了重载,所以会发生异常
- iOS内存管理——autorelease方法解析
- iOS 非ARC内存管理 autorelease方法和@autoreleasepool
- OC基础—内存管理之autorelease
- IOS基本内存管理:autorelease和autorelease pool
- 黑马程序员——IOS基础——OC内存管理循环retain和autorelease
- iOS学习————Objective C内存管理之理解autorelease
- IOS 学习之 —— 内存管理alloc,assign,retain,copy,release,autorelease
- IOS开发基础Object-C(10)—OC内存管理(4)-autorelease使用
- iOS基本内存管理:autorelease和autoreleasepool
- iOS基本内存管理:autorelease和autoreleasepool
- OC内存管理release、autorelease和set方法内存管理
- Objective C内存管理——如何理解autorelease
- Objective C内存管理——如何理解autorelease
- Objective C内存管理——如何理解autorelease pool
- 内存管理 之autorelease
- 内存管理4-@autorelease
- 内存管理4-@autorelease
- 内存管理之autorelease
- NE40E全业务路由器
- [LeetCode]9. Palindrome Number
- ffmpeg视频上传功能常用的俩个工具类【1.视频转码=2.视频抓图】
- substring用法总结
- Python strip lstrip rstrip使用方法
- iOS内存管理——autorelease方法解析
- Java注解(Annotation)
- SS3.2_Hibernate_Annotation 使用Annotation注解实现的Hibernate范例
- Android 中显示特殊字符
- tomcat支持远程调试
- jquery改变checkbox状态及判断checkbox是否选中
- 算法训练 出现次数最多的整数
- activemq 安装基本命令及持久化设置
- A problem was found with the configuration of task ':app:packageDebug'