2014-08-29 82 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