一、什么是 autorelease&autoreleasePool
- 1、对象执行
autorelease
方法或者直接在autoreleasePool
中创建对象,会将对象添加到autoreleasePool
中,当自动释放池销毁的时候,会对所有对象做release
操作 - 2、ARC的规则:
-
alloc/new/copy/mutableCopy
开头的方法(类方法和实例方法)返回的对象不是autorelease
对象 -
init
开头的方法(实例方法)返回的对象不是autorelease
对象
-
- 3、显示添加
AutoreleasePool
- 3.1、
NSAutoreleasePool
(只能在 MRC下使用) - 3.2、
@autoreleasePool{}
(ARC和 MRC均适用) - 3.3、显示调用
@autoreleasePool{}
,只有是autorelease
对象才会立刻释放;不是autorelease
对象添加或不添加没有什么用,都会立刻释放;自动释放池起到一个延迟释放的作用。
- 3.1、
1、代码一
- (void)dealloc
{
NSLog(@"LGMan dealloc");
}
+ (instancetype)object{
return [[LGMan alloc] init];
}
实例一、不会发送autorelease方法,不会注册到自动释放池当中;alloc/init/new/copy/mutableCopy开头的方法返回的对象不是autorelease对象,所以会在出了作用域就直接释放了
__weak id tmp = nil;
{
LGMan *man = [[LGMan alloc] init];
tmp = man;
}
NSLog(@"tmp == %@",tmp);
2019-09-17 10:27:13.073186+0800 LGAutoRelaseTest[10073:2217243] LGMan dealloc
2019-09-17 10:27:13.073317+0800 LGAutoRelaseTest[10073:2217243] tmp == (null)
实例二、发送autorelease方法,注册到自动释放池当中;autorelease对象,会在自动释放池销毁的时候释放
__weak id tmp = nil;
{
LGMan *man = [LGMan object];
tmp = man;
}
NSLog(@"tmp == %@",tmp);
2019-09-17 10:32:16.558413+0800 LGAutoRelaseTest[10142:2239041] tmp ==
2019-09-17 10:32:16.560429+0800 LGAutoRelaseTest[10142:2239041] LGMan dealloc
实例三、MRC下手动发送autorelease,就算不是autorelease对象 也会加入到自动释放池当中
int main(int argc, const char * argv[]) {
@autoreleasepool {
__weak id tmp = nil;
{
NSObject *man = [[NSObject alloc] autorelease];//MRC,手动发送autorelease,会加入到自动释放池。打印 tmp ==
// NSObject *man = [NSObject alloc];//ARC,因为不是autorelease对象,所以不会自动发送autorelease,所以不会加入到自动释放池。打印 tmp == (null)
tmp = man;
}
NSLog(@"tmp == %@",tmp);
}
return 0;
}
实例四、{}
作用域
__weak id tmp = nil;
LGMan *man = [LGMan object];
tmp = man;
NSLog(@"tmp == %@",tmp);
2019-09-17 10:38:53.335993+0800 LGAutoRelaseTest[10242:2269366] tmp ==
2019-09-17 10:38:53.337869+0800 LGAutoRelaseTest[10242:2269366] LGMan dealloc
__weak id tmp = nil;
LGMan *man = [[LGMan alloc] init];
tmp = man;
NSLog(@"tmp == %@",tmp);
2019-09-17 10:41:58.412400+0800 LGAutoRelaseTest[10283:2281480] tmp ==
2019-09-17 10:41:58.412501+0800 LGAutoRelaseTest[10283:2281480] LGMan dealloc
2、代码二
+ (NSString *)allocLGString{
// return [[NSString alloc] initWithString:@"HelloLGLGLG"];
// return @"HelloLGLGLG";
// 不会帮我们插入autorelease方法
// return [NSString stringWithFormat:@"HelloLGLGLG"];
// "Hello" Taggpointer,返回不能称之为对象,只有长度大于10的时候,返回才能称之为对象
// initWithCString这个方法会帮我们插入autorelease方法
// return [[NSString alloc] initWithCString:"Hello" encoding:NSUTF8StringEncoding];
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)newLGString{
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)copyLGString{
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)initLGString{
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)helloLGString{
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)createLGString{
return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
@autoreleasepool {
//nil autorelease
__weak NSString *tmp1 = [LGMan allocLGString];
__weak NSString *tmp2 = [LGMan newLGString];
__weak NSString *tmp3 = [LGMan copyLGString];
NSLog(@"%@",tmp1);
NSLog(@"%@",tmp2);
NSLog(@"%@",tmp3);
//hello world autorelease , 自动释放池当中!!!
__weak NSString *tmp4 = [LGMan initLGString];
__weak NSString *tmp5 = [LGMan createLGString];
__weak NSString *tmp6= [LGMan helloLGString];
NSLog(@"%@",tmp4);
NSLog(@"%@",tmp5);
NSLog(@"%@",tmp6);
}
2019-09-17 11:23:35.038652+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038770+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038853+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038952+0800 LGAutoRelaseTest[10913:2426586] HelloHello
2019-09-17 11:23:35.039029+0800 LGAutoRelaseTest[10913:2426586] HelloHello
2019-09-17 11:23:35.039134+0800 LGAutoRelaseTest[10913:2426586] HelloHello
3、代码三
显示添加AutoreleasePool
@autoreleasepool {
//LLVM autorelease
id object = [[NSObject alloc] init];
}
//1、生成一个 NSAutoreleasePool 对象
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//2、调用 Autorelease 方法
id object = [[NSObject alloc] init];
[object autorelease];
//3、废弃 NSAutoreleasePool 对象
[pool drain]; //object relase消息
显示调用autoreleasepool
对照实例二输出结果
__weak id tmp = nil;
@autoreleasepool {
LGMan *man = [LGMan object];
tmp = man;
}
NSLog(@"tmp == %@",tmp);
2019-09-17 12:13:19.639192+0800 LGAutoRelaseTest[11431:2536940] LGMan dealloc
2019-09-17 12:13:19.639332+0800 LGAutoRelaseTest[11431:2536940] tmp == (null)
二、打印:_objc_autoreleasePoolPrint()
#import
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
for (int i = 0; i < 5; i++) {
NSObject *objc = [[NSObject alloc] autorelease];
}
_objc_autoreleasePoolPrint();
}
return 0;
}
0x101003000 -> 0x101003038: 3*16+8 = 56
objc[45587]: ##############
objc[45587]: AUTORELEASE POOLS for thread 0x1000d1dc0
objc[45587]: 6 releases pending.
objc[45587]: [0x101003000] ................ PAGE (hot) (cold)
objc[45587]: [0x101003038] ################ POOL 0x101003038
objc[45587]: [0x101003040] 0x100619300 NSObject
objc[45587]: [0x101003048] 0x1007026b0 NSObject
objc[45587]: [0x101003050] 0x100702da0 NSObject
objc[45587]: [0x101003058] 0x100701d80 NSObject
objc[45587]: [0x101003060] 0x101b01ec0 NSObject
objc[45587]: ##############
Program ended with exit code: 0
16 + 8 + 8 + 8 + 8 + 4 + 4 = 56
class AutoreleasePoolPage : private AutoreleasePoolPageData(结构体)
- magic 用来校验 AutoreleasePoolPage 的结构是否完整;
- next 指向最新添加的 autoreleased 对象的下一个位置,初始化时指向begin() ;
- thread 指向当前线程;
- parent 指向父结点,第一个结点的 parent 值为 nil ;
- child 指向子结点,最后一个结点的 child 值为 nil ;
- depth 代表深度,从 0 开始,往后递增 1;
- hiwat 代表 high water mark 最大入栈数量标记
(4096-56) / 8 = 505
i < 505时,开始出现满页了,1+504+1
i < 505+505时,1+504+505+1
每一页的大小时505,由于第一页有边界(哨兵),所以第一页最多放504个8字节对象,之后的每一页最多放505个8字节对象。
#import
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
for (int i = 0; i < 505; i++) {
NSObject *objc = [[NSObject alloc] autorelease];
}
_objc_autoreleasePoolPrint();
}
return 0;
}
objc[45730]: ##############
objc[45730]: AUTORELEASE POOLS for thread 0x1000d1dc0
objc[45730]: 506 releases pending.
objc[45730]: [0x101003000] ................ PAGE (full) (cold)
objc[45730]: [0x101003038] ################ POOL 0x101003038
objc[45730]: [0x101003040] 0x100622110 NSObject
objc[45730]: [0x101003048] 0x100622f00 NSObject
objc[45730]: [0x101003050] 0x1006222e0 NSObject
.
.
.
objc[45730]: [0x101003fe8] 0x10062c8f0 NSObject
objc[45730]: [0x101003ff0] 0x10062c900 NSObject
objc[45730]: [0x101003ff8] 0x10062c910 NSObject
objc[45730]: [0x101001000] ................ PAGE (hot)
objc[45730]: [0x101001038] 0x10062c920 NSObject
objc[45730]: ##############
三、@autoreleasepool与线程,@autoreleasepool嵌套
#import
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *objc = [[NSObject alloc] autorelease];
NSLog(@"*****%@",objc);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// NSObject *objc = [[NSObject alloc] autorelease];
// NSLog(@"-----:%@",objc);
// _objc_autoreleasePoolPrint();
/**
1,@autoreleasepool 与线程关联
2,@autoreleasepool 嵌套,只会创建一个page,但是两个哨兵
*/
@autoreleasepool {
NSObject *objc = [[NSObject alloc] autorelease];
NSLog(@"-----:%@",objc);
_objc_autoreleasePoolPrint();
}
});
_objc_autoreleasePoolPrint();
sleep(3);
}
return 0;
}
1,@autoreleasepool 与线程关联
NSObject *objc = [[NSObject alloc] autorelease];
NSLog(@"-----:%@",objc);
_objc_autoreleasePoolPrint();
2020-03-23 18:13:22.773330+0800 ClangTest[46295:1287347] *****
objc[46295]: ##############
objc[46295]: AUTORELEASE POOLS for thread 0x1000d2dc0
objc[46295]: 2 releases pending.
objc[46295]: [0x100805000] ................ PAGE (hot) (cold)
objc[46295]: [0x100805038] ################ POOL 0x100805038
objc[46295]: [0x100805040] 0x100537f10 NSObject
2020-03-23 18:13:22.774101+0800 ClangTest[46295:1287749] -----:
objc[46295]: ##############
objc[46295]: ##############
objc[46295]: AUTORELEASE POOLS for thread 0x70000ec1d000
objc[46295]: 2 releases pending.
objc[46295]: [0x103800000] ................ PAGE (hot) (cold)
objc[46295]: [0x103800038] ################ POOL 0x103800038
objc[46295]: [0x103800040] 0x103200000 NSObject
objc[46295]: ##############
Program ended with exit code: 0
2,@autoreleasepool 嵌套,只会创建一个page(page的创建是来源于线程的),但是两个哨兵(哨兵的创建是来源于作用域空间)
@autoreleasepool {
NSObject *objc = [[NSObject alloc] autorelease];
NSLog(@"-----:%@",objc);
_objc_autoreleasePoolPrint();
}
2020-03-23 17:59:07.337042+0800 ClangTest[46239:1280138] *****
objc[46239]: ##############
objc[46239]: AUTORELEASE POOLS for thread 0x1000d2dc0
objc[46239]: 2 releases pending.
objc[46239]: [0x10200c000] ................ PAGE (hot) (cold)
2020-03-23 17:59:07.337869+0800 ClangTest[46239:1280172] -----:
objc[46239]: [0x10200c038] ################ POOL 0x10200c038
objc[46239]: [0x10200c040] 0x1006abba0 NSObject
objc[46239]: ##############
objc[46239]: ##############
objc[46239]: AUTORELEASE POOLS for thread 0x70000c8dc000
objc[46239]: 3 releases pending.
objc[46239]: [0x103800000] ................ PAGE (hot) (cold)
objc[46239]: [0x103800038] ################ POOL 0x103800038
objc[46239]: [0x103800040] ################ POOL 0x103800040
objc[46239]: [0x103800048] 0x103100040 NSObject
objc[46239]: ##############
Program ended with exit code: 0