为什么将静态引用传递给类消耗内存?

时间:2014-08-29 04:17:17

标签: ios objective-c j2objc

instruments screen capture

我很难理解为什么这会消耗内存。

我试过了;

  1. 允许更多时间清理ARC
  2. 创建全局的__weak副本以传递
  3. 看着使用__bridge或__bridge_transfer,但我不认为这是合适的。
  4. 将全局变量公开并直接引用它(有效,但不切实际)
  5. 此iOS Objective c线程通过j2objc 0.9.3从Java App转换。

    @implementation Comms_StatusThread
    
    - (void)run {
    while (true) {
    
        // Consumes memeory at aproximately 100k per 5 min
        [S globals];
    
        @try {
            [JavaLangThread sleepWithLong:10];
        }
        @catch (JavaLangInterruptedException *e) {
        }
    }
    

    这个翻译的静态单例存储“全局”可以从应用程序的任何地方访问(真正的代码存储更多的类和回调)。

    @implementation S
    
    Globals * S_globals__ = nil;
    
    + (Globals *)globals {
        {
            if (S_globals__ == nil) S_globals__ = [[Globals alloc] init];
            return S_globals__;
        }
    }
    
    @end
    

    任何帮助表示赞赏。我是Objective-c和ARC的新手。我已经阅读了相当数量的ARC,但仍然不明白这种内存消耗的原因。


    感谢Student T,我尝试了以下内容。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(test:) userInfo:nil repeats:YES];
        return YES;
    }
    
    -(void) test: (NSObject*) o {
        [S comms];
        [S globals];
    }
    

    这不消耗内存而且我打算这样做但是 tball的新答案(使用j2objc @AutoreleasePool)显然是最好的选择,所以我将从那里开始。

    非常感谢你的所有答案!

3 个答案:

答案 0 :(得分:2)

S_globals不是静态的;它显然缺少static modifier关键字。因此,每次循环时都要创建一个新的,这是不断发生的。

坦率地说,那段代码很可怕。帮助每个人,不要使用Java翻译。

答案 1 :(得分:1)

如果需要编写一个不断创建对象的循环,无论是否使用ARC,内存都会增长。 ' A'在ARC中是自动",因为其目的是自动使用保留/释放/自动释放方法。这些方法不会消除ARC,它们只是由编译器而不是开发人员处理。

为长期存在的对象(如线程池执行程序,单元测试运行程序和基准测试)添加的j2objc是AutoreleasePool注释,它(毫不奇怪)生成" @autoreleasepool {...}& #34 ;.此注释可用于方法和循环变量声明(在Java 7中不在其他地方,因为注释需要声明,但我们能够改进对Java 8的支持)。由于创建和耗尽自动释放池会损害性能,因此请选择合理大小的工作" chunk",例如以下示例:

public void run() { while (true) { for (@AutoreleasePool int i = 0; i < 10000; i++) { S.globals(); } } }

只要你的心愿,你应该能够运行它而不会耗尽内存。

答案 2 :(得分:0)

假设您正在使用ARC进行编译,因为如果不是,则整个转换毫无意义。您的实验无效,因为您将代码置于无限循环中。你试图睡眠线程,但它不会工作,因为你也在同时停止主运行线程。你需要让主运行循环有机会在10s的持续时间内运行。