web-dev-qa-db-ja.com

System.gc()はいつ何かをしますか?

ガベージコレクションはJavaで自動化されることを知っています。しかし、コードでSystem.gc()を呼び出すと、JVMがその時点でガベージコレクションを実行することを決定する場合としない場合があることを理解しました。これはどのように正確に機能しますか? JVMは、System.gc()を検出したときにGCを実行する(または実行しない)ことを正確にどの基準/パラメーターで決定しますか?

あなたのコードにこれを入れるのが良いアイデアの例はありますか?

111
harry

実際には、それは通常ガベージコレクションを行うことを決定します。答えは、実行しているJVM、使用しているモード、使用しているガベージコレクションアルゴリズムなど、多くの要因によって異なります。

私はあなたのコードでそれに依存しません。 JVMがOutOfMemoryErrorをスローしようとしている場合、System.gc()を呼び出しても停止しません。これは、ガベージコレクターが極端になる前にできる限り解放しようとするためです。実際に使用しているのは、ユーザーがクリックできるボタンにアタッチされているIDEでのみですが、それでもそれほど便利ではありません。

58
jodonnell

System.gc()を呼び出すことが理にかなっている唯一の例は、メモリリークの可能性を検索するためにアプリケーションをプロファイリングするときです。プロファイラーは、メモリのスナップショットを撮る直前にこのメソッドを呼び出すと思います。

29

Java言語仕様は、System.gc()を呼び出したときにJVMがGCを開始することを保証していません。これが、「その時点でGCを実行するかどうかを決定する場合としない場合」の理由です。

ここで、Oracle JVMのバックボーンである OpenJDKソースコード を見ると、System.gc()の呼び出しがGCサイクルを開始していることがわかります。 J9などの別のJVMを使用する場合は、ドキュメントを確認して答えを見つける必要があります。たとえば、AzulのJVMには継続的に実行されるガベージコレクターがあるため、System.gc()への呼び出しは何もしません

他のいくつかの回答では、JConsoleまたはVisualVMでGCを開始することに言及しています。基本的に、これらのツールはSystem.gc()へのリモート呼び出しを行います。

通常、アプリケーションのセマンティクスを台無しにするため、コードからガベージコレクションサイクルを開始する必要はありません。アプリケーションはいくつかのビジネスを行い、JVMがメモリ管理を行います。これらの懸念を分離しておく必要があります(アプリケーションにメモリ管理を行わせず、ビジネスに専念します)。

ただし、System.gc()への呼び出しが理解できる場合はほとんどありません。たとえば、マイクロベンチマークを検討してください。マイクロベンチマークの途中でGCサイクルを実行したい人はいません。したがって、各測定の間にGCサイクルをトリガーして、すべての測定が空のヒープで開始されるようにすることができます。

24
Pierre Laporte

JavaでGCを制御することはできません-VMが決定します。 System.gc()neededである場合に出会ったことはありません。 System.gc()呼び出しは、単にVMがガベージコレクションを行い、フルガベージコレクション(多世代ヒープの古い世代と新しい世代)を行うことを単に示唆するため、実際に発生する可能性があります- MORE CPUサイクルが必要以上に消費される。

場合によっては、VMに今すぐ完全なコレクションを行うことを提案するのが理にかなっているかもしれません。たとえば、アプリケーションの起動中に多数の一時オブジェクトを初期化した直後(つまり、情報のTONをキャッシュしただけで、1分間ほど多くのアクティビティが発生しないことを知っています)。 Eclipseの起動などのIDEを考えてみてください。初期化が非常に多いため、初期化後すぐに、その時点で完全なgcを実行するのが理にかなっています。

23
DustinB

System.gc()を呼び出す場合は、非常に注意する必要があります。それを呼び出すと、アプリケーションに不要なパフォーマンスの問題が追加される可能性があり、実際にコレクションを実行することは保証されません。実際には、Java引数-XX:+DisableExplicitGCを介して明示的なSystem.gc()を無効にすることができます。

ガベージコレクションの詳細については、 Java HotSpot Garbage Collection にあるドキュメントを読むことを強くお勧めします。

17

System.gc()はVMによって実装され、その機能は実装固有です。たとえば、実装者は単に戻って何もしません。

手動収集をいつ実行するかについては、これを実行する必要があるのは、小規模なコレクション(たとえば、Map<String,<LinkedList>>)のロードを含む大きなコレクションを放棄し、perfヒットを試してみたいときだけです。そこに、しかしほとんどの場合、あなたはそれを心配するべきではありません。ほとんどの場合、GCはあなたよりも(悲しいことに)よく知っています。

10
Patrick

ダイレクトメモリバッファを使用すると、ダイレクトメモリが不足していても、JVMはGCを実行しません。

ByteBuffer.allocateDirect()を呼び出してOutOfMemoryErrorが発生した場合、GCを手動でトリガーした後、この呼び出しで問題ないことがわかります。

8
Peter Lawrey

ほとんどのJVMはGCを開始します(-XX:DiableExplicitGCおよび-XX:+ ExplicitGCInvokesConcurrentスイッチに依存)。しかし、後でより良い実装を可能にするために、仕様の定義が不十分です。

バグ#6668279:(spec)System.gc()は、使用を推奨せず、動作を保証しないことを示す必要があります

内部的にgcメソッドはRMIとNIOによって使用され、それらは同期実行を必要とします。これは現在議論中です。

バグ#5025281:System.gc()が並行(完全停止ではない)フルコレクションをトリガーできるようにする

5
eckes

デスクトップ/ラップトップ/サーバーでJavaでコーディングされたソフトウェアを実行している場合、Garbage CollectionJavaで適切です。 JavaSystem.gc()またはRuntime.getRuntime().gc()を呼び出すことができます。

これらの呼び出しはどれも何もすることが保証されていないことに注意してください。 jvmがガベージコレクターを実行するための単なる提案です。 GCを実行するかどうかにかかわらず、それはJVMの責任です。簡単な答え:いつ実行されるかわかりません。より長い答え:JVMは、時間があればgcを実行します。

同じことがAndroidにも当てはまると思います。ただし、これによりシステムの速度が低下する可能性があります。

2
Naveen

通常、VMはOutOfMemoryExceptionをスローする前にガベージコレクションを自動的に実行するため、明示的な呼び出しを追加しても、パフォーマンスヒットが以前の瞬間に移動する可能性があることを除いては役に立ちません。

しかし、私はそれが関連するかもしれないケースに遭遇したと思います。ただし、効果があるかどうかはまだテストしていないので、わかりません。

ファイルをメモリマップすると、十分な大きさのメモリブロックが利用できない場合にmap()呼び出しがIOExceptionをスローすると思います。 map()ファイルの直前のガベージコレクションは、それを防ぐのに役立つと思います。どう思いますか?

2
Vashek

ガベージコレクションを強制することはできません。 System.gcはガベージコレクション用にvmのみを提案していますが、実際には、メカニズムが実行される時間は誰にもわかりません。これはJSR仕様で述べられているとおりです。

2
lwpro2

さまざまなガベージコレクション設定をテストするのに時間がかかると言われるLOTがありますが、前述のように、通常はそうすることは役に立ちません。

私は現在、メモリが制限された環境と比較的大量のデータを含むプロジェクトに取り組んでいます-私の環境を限界に押し上げるいくつかの大きなデータがあり、メモリ使用量を下げることができたにもかかわらず理論上は問題なく動作するはずですが、ヒープスペースエラーが発生することになります。詳細なGCオプションを使用すると、ガベージコレクションを試みていることがわかりましたが、役に立ちませんでした。デバッガーでSystem.gc()を実行すると、十分なメモリが十分にあることを確認できました...余分なメモリではなく、十分なメモリです。

その結果、アプリケーションがSystem.gc()を呼び出すのは、データの処理に必要な大きなバッファが割り当てられるコードセグメントに入ろうとしているときだけであり、利用可能な空きメモリのテストは、それを持っていることが保証されています。特に、少なくとも300mbが静的データで占められ、処理中のデータが少なくとも100-200 MBである場合を除き、非静的データの大部分が実行関連である1gb環境を探しています。起源。それはすべて自動データ変換プロセスの一部であるため、長期的にはデータはすべて比較的短期間存在します。

残念ながら、ガベージコレクターを調整するためのさまざまなオプションに関する情報は入手可能ですが、それは主に実験的なプロセスであり、これらの特定の状況を処理する方法を理解するために必要な下位レベルの詳細は容易に取得できません。

そうは言っても、System.gc()を使用しているにもかかわらず、コマンドラインパラメータを使用して調整を続け、アプリケーションの全体的な処理時間を比較的大きく改善することができました。より大きなデータのブロックを操作することによって引き起こされる障害。そうは言っても、System.gc()はツールであり、非常に信頼性の低いツールです。使用方法に注意を払わない場合、あまり頻繁に機能しないことを望みます。

2
Kyune

要するに:

パラメーターはVM依存です。

使用例-ランタイム/プロダクションアプリの場合は考えられませんが、次のようなプロファイリングハーネスに対して実行すると便利です。

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();
1
mataal

System.gc()が呼び出されたかどうかを知りたい場合は、新しいJava 7 update 4で、JVMがガベージコレクションを実行するときに通知を受け取ることができます。

GarbageCollectorMXBean クラスがJava 7 update 4で導入されたことは100%確信できませんが、リリースノートで見つけることができませんでしたが、 javaperformancetuning 。comサイト

1
Shervin Asgari

Bruce EckelによるThinking in Javaによると、明示的なSystem.gc()呼び出しの使用例の1つは、強制的にファイナライズする場合です。 finalizeメソッドの呼び出し。

0
Asterisk

明示的なGCを実行することが適切な場合、特定の例を考えることはできません。

一般に、明示的なGCを実行すると、実際よりも害が大きくなる可能性があります。これは、明示的なgcが完全なコレクションをトリガーするためです。この明示的なgcが繰り返し呼び出されると、フルGCの実行に多くの時間が費やされるため、アプリケーションが低速になりやすくなります。

または、ヒープアナライザでヒープを調べて、ライブラリコンポーネントが明示的なGCを呼び出していると疑われる場合は、JVMパラメータにgc = -XX:+ DisableExplicitGCを追加してオフにすることができます。

0
zxcv

system.gcは機能しますが、ワールドを停止します。すべてのレスポンが停止されるため、ガベージコレクターはすべてのオブジェクトをスキャンして、削除する必要があるかどうかを確認できます。アプリケーションがWebプロジェクトの場合、gcが終了するまですべての要求が停止します。これにより、Webプロジェクトがmonentで動作できなくなります。

0
fleture