autorelease&autoreleasePool

一、什么是 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对象添加或不添加没有什么用,都会立刻释放;自动释放池起到一个延迟释放的作用。

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

你可能感兴趣的:(autorelease&autoreleasePool)