1

インストゥルメントの画面キャプチャ

これがメモリを消費している理由を理解するのに苦労しています。

私が試してみました;

  1. ARC がクリーンアップするための時間を増やす
  2. 渡すグローバルの __weak コピーの作成
  3. __bridge または __bridge_transfer の使用を検討しましたが、これは適切ではないと思います。
  4. グローバルを公開して直接参照する (機能しますが、実用的ではありません)

この iOS Objective 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 についてかなりの量を読みましたが、このメモリ消費の原因をまだ理解していません。


Student TIのおかげで、次のことを試しました。

- (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 を使用) が明らかに最良の選択肢であるため、そこから始めます。

ご回答ありがとうございます。

4

3 に答える 3

2

S_globals は静的ではありません。static 修飾子キーワードが明らかに欠けています。したがって、ループするたびに新しいものを作成しています。これは継続的に発生しています。

率直に言って、そのコードは恐ろしいものです。Java トランスレータは使用しないでください。

于 2014-08-29T04:47:13.820 に答える
1

オブジェクトを継続的に作成するループを記述する必要がある場合、ARC を使用するかどうかに関係なくメモリが増加します。ARC の「A」は「自動」です。その目的は、retain/release/autorelease メソッドの使用を自動化することです。これらのメソッドは ARC ではなくなりません。開発者ではなく、コンパイラによって処理されるだけです。

j2objc が有効期間の長いオブジェクト (スレッド プール エグゼキューター、ユニット テスト ランナー、ベンチマークなど) に追加したのはAutoreleasePoolアノテーションで、これは (驚くことではありませんが) "@autoreleasepool { ... }" を生成します。この注釈は、メソッドおよび for ループ変数の宣言で使用できます (Java 7 の他の場所では注釈が宣言を必要とするため使用できませんが、Java 8 でサポートを改善することができます)。自動解放プールを作成して排出するとパフォーマンスが低下するため、次の例のように適切なサイズの作業「チャンク」を選択します。

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

メモリが不足することなく、心が望む限りこれを実行できるはずです。

于 2014-08-29T17:23:50.203 に答える
0

ARC を使用してコンパイルしていると仮定すると、そうでない場合、変換全体が無意味になるためです。コードを無限ループに入れるため、実験は機能しません。スレッドをスリープさせようとしましたが、実行中のメイン スレッドも同時に停止していたため、機能しませんでした。メインの実行ループに 10 秒間実行する機会を与える必要があります。

于 2014-08-29T04:54:00.663 に答える