Javaプログラマーは、JVMがガベージコレクターを実行することを知っています。System.gc()は、ガベージコレクターを実行するためのJVMへの提案にすぎません。 System.gc()を使用すると、GCがすぐに実行されるとは限りません。
Javaのガベージコレクターを誤解した場合は訂正してください。
Javaのガベージコレクターに依存する以外に、メモリ管理を行う他の方法はありますか?
メモリの管理に役立つ、ある種のプログラミング実践によって質問に回答するつもりなら、そうしてください。
Javaメモリ管理について覚えておくべき最も重要なことは、参照を「無効にする」ことです。
参照されていないオブジェクトのみがガベージコレクションの対象になります。
たとえば、次のコードのオブジェクトは収集されず、何もしないためにメモリがいっぱいになります。
_List objs = new ArrayList();
for (int i = 0; i < Integer.MAX_VALUE; i++) objs.add(new Object());
_
しかし、これらのオブジェクトを参照しない場合は、メモリの問題なしに好きなだけループできます。
_List objs = new ArrayList();
for (int i = 0; i < Integer.MAX_VALUE; i++) new Object();
_
したがって、何をするにしても、オブジェクトへの参照を削除して、もう使用しないようにしてください(null
への参照を設定するか、コレクションをクリアします)。
ガベージコレクターをいつ実行するかは、JVMに任せるのが最善です。まあ、プログラムがメモリを大量に使用し、速度が重要なものに取り掛かる場合を除いて、ガベージコレクションと余分なメモリが発生する可能性があるため、JVMを実行する前にGCを実行することをお勧めします。そうでなければ、個人的にはSystem.gc()
を実行する理由はないと思います。
この助けを願っています。
以下は、私が昔に書いた小さな要約です(私はいくつかのブログからそれを盗みましたが、どこから来たのか思い出せません-参照なし、申し訳ありません)
-Xms
および-Xmx
は、Javaヒープの開始サイズと最大サイズを設定するために使用されます。このパラメーターの理想的な比率は、私の経験に基づいて1:1または1:1.5です。たとえば、両方とも –Xmx
および–Xms
1GBまたは–Xms 1.2 GBおよび1.8 GB。コマンドラインオプション:-Xms:<min size> -Xmx:<max size>
ディスカッションに追加するだけです:ガベージコレクションはJavaのメモリ管理の唯一の形式ではありません。
過去には、メモリ管理を実装するときに、JavaでGCを回避するための努力が行われてきました( リアルタイム仕様Java( RTSJ) )。これらの取り組みは主に、リアルタイムの埋め込みプログラミングにJavaパフォーマンスオーバーヘッドまたはGCに起因するレイテンシのために、GCが適していなかったJava $ ===)に捧げられました。
RTSJの特性
RTSJの利点:
RTSJが失敗した理由/大きな影響はありませんでした:
スコープ付きメモリのコード例(スコープ付きメモリの使用例= からの引用 ):
import javax.realtime.*;
public class ScopedMemoryExample{
private LTMemory myMem;
public ScopedMemoryExample(int Size) {
// initialize memory
myMem = new LTMemory(1000, 5000);
}
public void periodicTask() {
while (true)) {
myMem.enter(new Runnable() {
public void run() {
// do some work in the SCOPED MEMORY
new Object();
...
// end of the enter() method, the scoped Memory is emptied.
}
});
}
}
}
ここでは、LTMemory
というScopedMemory実装が事前に割り当てられています。次に、スレッドはスコープメモリに入り、計算時にのみ必要な一時データを割り当てます。計算の終了後、スレッドはスコープメモリを離れ、特定のScopedMemoryのコンテンツ全体がすぐに空になります。レイテンシは導入されず、一定の時間で実行されます。予測可能な時間、GCはトリガーされません。
Javaを使用している場合は、ガベージコレクションを回避できません。多分、あいまいなJVM実装がいくつかあるかもしれませんが、私は知りません。
適切に調整されたJVMは、スムーズに動作するためにSystem.gc()ヒントを必要としないはずです。必要となる正確なチューニングは、アプリケーションの動作に大きく依存しますが、私の経験では、次のフラグを使用して、コンカレントマークアンドスイープオプションを常にオンにしています:-XX:+UseConcMarkSweepGC
。このフラグにより、JVMはCPUの追加コアを利用して、バックグラウンドスレッドのデッドメモリをクリーンアップできます。これは、ガベージコレクションを実行するときにプログラムが強制的に一時停止される時間を大幅に削減するのに役立ちます。
私の経験から、Javaでは、JVM自体によって提供されるメモリ管理に依存する必要があります。
このトピックで焦点を当てるのは、ユースケースに受け入れられる方法で構成することです。たぶん、JVMチューニングオプションをチェック/理解すると便利でしょう: http://docs.Oracle.com/cd/E15523_01/web.1111/e13814/jvm_tuning.htm
System.gc()
はコンパイラへのリクエストであり、コマンドではないというのは正しいことです。しかし、以下のプログラムを使用すると、それが発生することを確認できます。
import Java.lang.ref.WeakReference;
public class GCRun {
public static void main(String[] args) {
String str = new String("TEMP");
WeakReference<String> wr = new WeakReference<String>(str);
str = null;
String temp = wr.get();
System.out.println("temp -- " + temp);
while(wr.get() != null) {
System.gc();
}
}
}
まあ、GCは常に存在します-ネイティブの呼び出しを使用したり、直接バイトバッファーを割り当てたりしない限り、把握できないオブジェクトを作成することはできませんが、後者の場合、実際にはオブジェクトがなく、ただの束ですバイト)。つまり、オブジェクトを再利用することで、GCを回避することは間違いなく可能です。たとえば、ArrayList
オブジェクトの束が必要な場合は、必要に応じてそれぞれを作成し、GCにメモリ管理を処理させることができます。または、それが終わった後、それぞれについてlist.clear()
を呼び出して、他の誰かがそれを使用できるキューに置くこともできます。
標準的なベストプラクティスはnotですが、十分な理由がない限り(つまり、割り当てとGCが問題であり、オブジェクトを再利用することで問題が修正されることをプロファイルして確認した場合を除き)、このような再利用を行います。 。それはより複雑なコードにつながり、あなたがそれを間違えた場合、GCが実際に(GCがオブジェクトを追跡する方法のために)仕事を難しくする可能性があります。
基本的にJava=の考え方は、「新規」を使用して新しいオブジェクトを割り当て、それを使い終わったときにオブジェクトへの参照が残っていないことを確認する以外は、メモリを処理しないことです。
残りはすべて、意図的にJavaランタイムに任せられ、また、意図的に-できるだけ漠然と定義されて、JVM設計者が効率的に実行するための最も自由なものになります。
類推を使用するには:オペレーティングシステムは、ハードディスク領域の名前付き領域(「ファイル」と呼ばれます)を管理します。もう使いたくないエリアの削除と再利用を含みます。そのメカニズムを回避するのではなく、オペレーティングシステムに任せる
明確でシンプルなコードを書くことに集中し、オブジェクトが適切に処理されるようにする必要があります。これにより、JVMは可能な限り最良の動作状態になります。
次のチュートリアルとその内容を確認することをお勧めします
これは、Java
のガベージコレクションの基本について知るための4部構成のチュートリアルシリーズです。
Javaガベージコレクションの紹介
Javaガベージコレクションの仕組み
タイプJavaガベージコレクター
監視と分析Javaガベージコレクション
私は このチュートリアル がとても役に立ったと感じました。
不要なときに参照を「無効にする」ことが、オブジェクトをガベージコレクションの対象にするための最良の方法です。
オブジェクトをガベージコレクションする方法は4つあります。 1.参照が不要になったら、参照をnullにポイントします。
String s = new String("Java");
この文字列が不要になったら、nullを指すことができます。
s = null;
したがって、sはガベージコレクションの対象になります。
あるオブジェクトを別のオブジェクトに向け、両方の参照が同じオブジェクトを指し、オブジェクトの1つがGCに適格になるようにします。
文字列s1 = new String( "Java");
文字列s2 = new String( "C++");
今後、s2もs1を指す必要がある場合、
s1 = s2;
そうすると、「Java」を持つオブジェクトがGCの対象になります。
メソッド内で作成されたすべてのオブジェクトは、メソッドが完了すると、GCの対象になります。したがって、メソッドがスレッドのスタックから破棄されると、そのメソッド内の対応するオブジェクトが破棄されます。
Island of Isolationは、内部リンクがあり、参照への外部リンクがないオブジェクトがガベージコレクションの対象となる別の概念です。 ガベージコレクションの「孤立の島」
例:以下は、AndroidのCameraクラスのメソッドです。開発者がmCameraSourceが不要になったらnullにポイントする方法を確認してください。これはエキスパートレベルのコードです。
public void release() {
if (mCameraSource != null) {
mCameraSource.release();
mCameraSource = null;
}
}
ガベージコレクターの仕組み
ガベージコレクションは、ガベージコレクタと呼ばれるデーモンスレッドによって実行されます。その時点で十分なメモリが利用可能な場合、このデーモンスレッドの優先度は低く、バックグラウンドで実行されます。しかし、JVMがヒープがいっぱいであることを検出し、JVMが一部のメモリを再要求する場合、ガベージコレクタスレッドの優先度を上げ、参照またはnull参照を持たないすべてのオブジェクトを検索するRuntime.getRuntime.gc()メソッドを呼び出します。それらのオブジェクトを破棄します。