-1

継続的に実行されているスレッドの run() から継続的に呼び出される次の関数があります。

private LinkedList<short[]> playerData = new LinkedList<short[]>();

public synchronized void setPlayerData(short[] buffer) {
        // Log.i(LOG_TAG, "Inside setData..");
        playerData.addLast(buffer);
        if (playerData.size() > 10) {
            // Log.i(LOG_TAG, "playerData not empty");
            playerData.removeFirst();
        }
    }

現在、DDMS の割り当てトラッカーは、多くのオブジェクトが addLast() 内 (実際には addLastImpl() 内) で作成されていることを示しています。そのため、配列を明示的に削除して、ヒープに常に十分なメモリを確保したいと考えています。今、

  1. System.gc() オプションは、setPlayerData() へのすべての呼び出しで同時に呼び出されるため、役に立ちません。
  2. GC_CONCURRENT はすべての CPU サイクルを消費しています。これは、アプリが時間に非常に敏感であり、数ミリ秒の遅延でさえ許容できないためです。

LogCat の情報については、リンクを参照してください。これは、シナリオン全体に対処する別の質問です。このスレッドでは、小さな問題のセットに分割することで、その大きな問題を解決しようとしています。

考えられる解決策考えられる解決策は、不要な配列を削除してメモリ空間を明示的に解放することです。newしかし、Java では、演算子によって作成された配列をどのように解放できますか? すなわち

short[] buffer = new short[320];
// do some operation on buffer
/// now how can I explicitly free memory by deleting the buffer, when its job is over..

そのようなことすべてを処理するためのガベージコレクションがあることを私は知っています。しかし、私のアプリではGC_CONCURRENTが常に食い尽くしています。これにより、他のプロセスが枯渇します。メモリを明示的に解放できる、つまり C++ で削除できればよかったのにと思います。ここで LogCat 情報を確認できます...私の問題に関する詳細な質問

EDIT 2 3.配列をnullに割り当てます

それはどのように役立ちますか?null 配列はガベージ コレクションにスケジュールされますが、メソッドはスレッドから継続的に (20 ミリ秒ごとに) 呼び出されるため、これは避けたいと考えています。配列を null に割り当てると、GC_FOR_MALLOC メッセージで LogCat がいっぱいになります...

4

5 に答える 5

7

オブジェクトを明示的に削除しても問題は解決されません...基本的にJavaでそれを行う方法がないためです。

CMS コレクターが対処できないほど大量のガベージを作成している場合、唯一の解決策は、GC が処理できるようにオブジェクトを床に落とすのではなく、オブジェクト プールを使用してオブジェクトをリサイクルすることですbuffer。ただし、現在の問題を他の問題に置き換えないように注意する必要があります。

  • リサイクルされたオブジェクトは、「クリーニング」(ゼロ化) する必要がある場合があります。
  • 適切に設計されていないオブジェクト プールは、メモリ リークの原因になる可能性があります。
  • 適切に設計されていないオブジェクト プールは、同時実行のボトルネックになる可能性があります。
  • 設計が不十分なオブジェクト プールは、特に小さすぎるヒープで実行している場合に、GC オーバーヘッドを増加させる可能性があります。

一方、実際の問題は、実行しようとしているアプリケーションに対してヒープが小さすぎることかもしれません。制限に近づきすぎると、GC は毎回多くのガベージを回収しません。GC の実行コストは NON ガベージの量に比例するため、ヒープがいっぱいに近づくにつれて GC の効率が非線形になることは容易にわかります。

于 2012-04-10T07:04:30.047 に答える
4

使用後にオブジェクトをNULLに設定するだけで、ガベージ コレクターが自動的に処理します。実際には、コードからオブジェクトにアクセスできない場合にガベージ コレクターが起動するため、オブジェクトを破棄してスペースを解放します。

于 2012-04-10T06:39:30.663 に答える
2

Java には削除演算子がありません。コード部分がオブジェクトを使用しなくなると、ガベージ コレクターはオブジェクトを自動的に破棄します。

つまり、オブジェクトが到達不能になると、ガベージ コレクターはそのオブジェクトを破棄し、関連するメモリを解放します。

編集を読みました。byte[] バッファ プールで問題を解決できるかもしれません。そのため、ガベージ コレクタは常にバッファをガベージする必要はありません。

private LinkedList playerData = new LinkedList();

public synchronized void setPlayerData(short[] buffer) {
  // Log.i(LOG_TAG, "Inside setData..");
  playerData.addLast(buffer);
  if (playerData.size() > 10) {
    // Log.i(LOG_TAG, "playerData not empty");
    byte[] buffer = playerData.removeFirst();
    // here return the buffer to the pool to reuse it
  }

  }

于 2012-04-10T06:36:29.730 に答える
1

ガベージコレクターに問題がある場合は、新しいメモリの割り当てを減らすのが最善の方法です。これを行う1つの方法は、オブジェクトプールを使用することです。基本的に、新しいバッファを作成する代わりに、不要になったバッファを再利用します。

于 2012-04-10T06:42:43.830 に答える
1

Java には「同等の」演算子はありません。システムはバックグラウンドでガベージ コレクションを実行します。明示的なメソッド呼び出しは、メモリがすぐに解放されることを保証しません。

于 2012-04-10T06:46:44.323 に答える