美文网首页
autorelease&autoreleasePool

autorelease&autoreleasePool

作者: Code_人生 | 来源:发表于2019-09-30 14:34 被阅读0次

    一、什么是 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 == <LGMan: 0x6000003942b0>
    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: 0x100614480>
    //            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 == <LGMan: 0x600002514530>
    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 == <LGMan: 0x600002c27df0>
    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 <Foundation/Foundation.h>
    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 <Foundation/Foundation.h>
    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 <Foundation/Foundation.h>
    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] *****<NSObject: 0x100537f10>
    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] -----:<NSObject: 0x103200000>
    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] *****<NSObject: 0x1006abba0>
    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] -----:<NSObject: 0x103100040>
    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

          本文链接:https://www.haomeiwen.com/subject/dipquctx.html