2009-05-22 4 views
1

私はJ2MEアプリケーションを維持する必要があります。アプリケーション内には多くのSystem.gc()があります。 System.gc()を呼び出す前に、すべての属性がnullに設定されています。属性をnullに設定することは意味がありますか? System.gc()と呼んでも意味がありますか? jvmが必要なときにガベージコレクタを呼び出すべきではありませんか?モバイルでSystem.gc()を呼び出す

答えて

1

属性とSystem.gc()呼び出しをすべて無効にする理由は、間違いなくデバイスの断片化との闘いの一部です。実際に値をnullにしてはいけません。範囲外にしておかなければなりません。実際には、これはPC開発のための適切な方法です。しかし、モバイルスペースはまったく別の動物であり、限られたモバイルデバイスでも同じようにメモリ管理を処理できるというのは無理なことです。

でも、ハイエンドのスマートフォンでは、J2MEアプリケーションで使用可能なヒープ数が約32〜64MBです。多くのデバイスは約1〜4MBであり、より小さいヒープサイズをターゲットにするために必要なキャリア仕様を満たすことがよくあります。 Razrは800Kのヒープしか持たず、多くの加入者が引き続きデバイスを使用しているため、ほとんどの通信事業者がサポートする必要があります。

メモリの断片化は、メモリのブロックがもはや使用されていなくても無効になっていても、ガーベジコレクションされるまで利用できません。ほとんどのモバイルVMは、メモリが必要な場合にのみGCを行います。最終的にGCを実行すると、ヒープは小さなメモリブロックに分割される可能性があります。より大きなメモリブロックが割り当てられる必要がある場合、それはより小さいブロックに割り当てることができなくなる。これらのより小さいブロックが十分にあり、ヒープを汚染し、大きなオブジェクトに十分な大きさのブロックを供給しない場合は、使用可能なメモリがたくさんあるように見えるかもしれませんが、最終的にOutOfMemory例外が発生します。

たとえば、50バイトを必要とするローカルObject変数を作成するとします。次に、200バイトのヒープが存在する必要があるアプリケーションの存続期間中存続するメンバ変数を割り当てます。このプロセスを何度も何度もやり直すと、長さが50バイトしかない何千ものブロックがある状況になる可能性があります。永続オブジェクトのために200バイトが必要なので、最終的には戸惑うことになり、OutOfMemory例外が発生します。

これで、同じStringオブジェクトを作成し、それを使用して自分自身をヌルルし、System.gc()を呼び出しました(また、Thread.yield()を呼び出してGCを実行できるようにすることもできます)新しい永続オブジェクトを作成し、フラグメンテーションを回避し、最終的なOutOfMemory例外を回避するために、これらの50バイトを使用できるようにします。

これは非常に基本的な例ですが、ゲームアプリケーションのような大きな画像がたくさんある場合は、モバイルスペースでこの状況に非常に迅速に遭遇します。

最後に注意しておきますが、BlackBerryデバイスでは、はるかに洗練されているためガーベッジコレクタを自分で呼び出すことは避けてください(ヒープを最適化する)。より洗練されているため、ほとんどのデバイスで通常のダウンしてダーティなGCよりもはるかに遅くなります(1回の実行で数秒)。

0

属性をnullに設定する(オブジェクトへの参照をいくつか破棄する)と、GCがそれらのオブジェクトを要求します。おそらくそれらはもはや必要ではなく、開発者は記憶を解放したいと思ったのだろうか?

私は、すべてのJ2MEターゲットがにはGCがであるとは聞いていません。しかし、そうであれば、System.gc()を呼び出すことで、リアルタイムの処理を行うときにガベージコレクタが起動しないようにすることができます。

+0

私は、VMがガベージコレクションを持つためのJava言語仕様の一部であることは間違いないと思いますが、プリミティブであるか悪いですか。私はあなたが仕様に準拠しているプラ​​ットフォーム用にプログラミングしていると仮定しなければならないと思います。 –

+0

GCが何をしなければならないかを定義するのはむしろ困難です。だから何もしないことは有効です。これは実装上の問題です。 JavaCardは異なるかもしれませんが、妥当な実装をしなければ深刻なJavaMEを見るのは非常に驚きです。 –

+0

System.gc()を呼び出すと、Java SEシステムのリアルタイム動作が改善されず、Java MEプラットフォームではそれほど役に立ちません。 –

2

良い現代的なVMでは、一般的にSystem.gc()をほとんど意味しません。属性に到達できないようにする唯一の方法でない限り、属性をnullに設定するのは一般的に意味がありません。

あまり洗練されていないVMでは、かもしれないモバイルデバイスを使用すると、メソッドの途中で使用されなくても、スコープ内にある場合は参照をnullにすることができます。 (Hotspotのような近代的なデスクトップVMでは、これは一般的には不要です.VMはコードの前にコードを持ち、スコープに関係なくローカル参照を使用するかどうかは一般的に分かります)

今、System.gc()に戻ってきたが、モバイルVMは、これまでよく使用されてきたかなり洗練された「本格的な」VMよりも単純なものでした。しかし、

  • モバイルVMは近年多くのものがあります。オブジェクトスループットは、パフォーマンスの他の側面と同様に、多くのデバイスで確実に向上しています。
  • いずれにしても、System.gc()には一貫した明確な動作がありません。デバイスによっては、まったく何もしない場合があります。デスクトップVMと同様に、アプリケーションの実行中にVMが自動的に実行する通常の「徐々に」ガベージコレクションと比較して、実際にパフォーマンスを低下させるタイプのガベージコレクションを引き起こす可能性があります。

私はSystem.gc()を使用することに非常に注意します。

2

これは、Javaの世界では、System.gc()を呼び出すことが、実際には信頼性の高い何かを行うための大きな都市伝説です。それはできません。

JVMが何かをしようとするのは単なる提案です。この点に関して、Javadoc for the methodは意図的にあいまいです。

他の大きなバグベアはヌル参照です。参照が範囲外になると、すでに参照されているので、自分自身が冗長で誤解を招くことがあります。他のリファレンスがまだ残っている場合、それらは引き続き使用可能になり、割り当ては何も行いません(VMがすでに実行していることです)。

だからあなたの質問に答えるために:めったにヌルないように属性を設定する

  • は理にかなっています。ソフトウェアを適切に設計して、使用しなくなった参照が範囲外になるようにします。
  • System.gc()を呼び出すことはめったに意味がありません。JVMがあなたのために仕事をするようにしましょう。そういうわけで、自分のメモリを管理するのではなく、VMを使用するのです。
  • はい、VMがあなたのメモリを管理するようにします。必要なときにGCになります。しかし、ソフトウェアの設計が不適切であれば、VM内のGCを無効にすることができます。この場合、メモリリークを追跡し、ソフトウェアをリファクタリングします(しかし、やったほうが簡単です)。
+0

どのようにメモリリークを追跡しますか? –

+1

、WilyまたはJProfilerのようなプロファイラを使用する –

2

これまでのこの質問に対するすべての回答は、まったく正しいものであり、主にSystem.gc()を使用して何かを行うことはできません。これはプラットフォーム固有のものであり、MIDP2はどのように動作すべきかについての実際の仕様を示していません。

しかし、「このオブジェクトはnowが削除されました」などとは言えませんが、通常は適切な方法で実装されていますが、特定の状況下ではこの呼び出しを使用することをお勧めします。例えば、あなたのアプリケーションが大量の削除と割り当て(例えば、状態のリセットや状態の変更)を実行する必要がある場合、直ちに呼び出しを行うとVMに通知されます。

James

関連する問題