2014-08-29 83 views
1

instruments screen capture为什么向类传递静态引用会消耗内存?

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

我试过了;

  1. 允许ARC更多的时间来清理
  2. 创建全局的__weak副本传递
  3. 看着使用__bridge或__bridge_transfer,但我不认为这是适当的。
  4. 使全局公共和直接引用它(作品,但不切实际的)

这个iOS的目标C线是从Java应用程序通过j2objc 0.9.3翻译。

@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上阅读过相当多的内容,但仍不明白这种内存消耗的原因。


感谢学生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)显然是最好的选择,所以我会从那里开始。

非常感谢您的答复!

+0

+1对于您的尝试 – SmallChess 2014-08-29 04:45:20

+1

“允许更多时间用于ARC清理”我不认为ARC以您认为的方式工作。 ARC在编译时只是为你插入发行版本。它不像Java那里有一个垃圾回收器可以扫描并释放事物。 – 2014-08-29 05:33:54

回答

0

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

2

S_globals不是静态的;它很明显缺少静态修饰符关键字。所以,每当你循环时,你都会创造一个新的,这是持续发生的。

坦率地说,那个代码是可怕的。请大家帮忙,不要使用Java翻译器。

+0

不完全。如果它使用ARC,我认为它是(因为他说),这不会是一个问题。 – SmallChess 2014-08-29 04:49:33

+0

此外,将其标记为静态只意味着该变量不能在源代码之外访问。 – SmallChess 2014-08-29 04:49:54

+3

从长远来看,它不会泄漏,但是由于代码处于一个紧密的无限循环中,ARC没有机会做到这一点。 JShier是正确的,代码是可怕的,OP会花更多的时间弄清楚为什么事情不能正确地写在ObjC – Paulw11 2014-08-29 04:50:39

1

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

j2objc为长寿命对象(如线程池执行器,单元测试运行器和基准测试)添加了什么是AutoreleasePool注释,这(毫不奇怪)会生成“@autoreleasepool {...}”。此注释可用于方法和循环变量声明(不在Java 7中的其他位置,因为注释需要声明,但我们将能够改进对Java 8的支持)。由于创建和排水自动释放池会损害性能,选择一个合理大小的作品“块”,如下面的例子:

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

你应该可以,只要你的心脏的欲望,但不运行运行此内存不足。

+0

@Lorne K:j2objc在课堂上使用吗?如果是这样,我们很乐意在[email protected]上听到您的体验。 – tball 2014-08-29 17:28:26

+0

哇 - 这太棒了。我明显应该在发布前更彻底地搜索j2objc网站。这不适用于学校 - 我们是一个18个月的初创公司。主要是硬件,但我有大约14000行Android代码,已经非常好地转换成Mac和iOS。由于硬件非常复杂 - 多种协议,加密类型,连接模式,数据类型等,因此真正节省生命。如果某项功能在Android中运行,则iOS/Mac翻译将始终完美运行。我们从来没有遇到过问题(只是内存问题)。也很好卸载这个东西,所以我可以做固件工作:) – 2014-08-30 03:57:06