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


118

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

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


4
コンセプトが複雑すぎて詳細はここまでですが、この記事が役立つはずです:chaoticjava.com/posts/how-does-garbage-collection-work
GEOCHET

正確な動作はJVMに依存します。つまり、実装に依存します。
–ThorbjørnRavn Andersen 2012

回答:


59

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

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


3
jconsoleでガベージコレクションを強制できます
Benedikt Waldvogel 2008

25
@bene本当に「強制」できますか?jconsoleはSystem.gc()を呼び出すだけですか?
John Meagher

4
System.gc()ビデオゲームの読み込み画面で使用します。その時点では、呼び出しが可能な限りすべてをクリアしたか、まったく何もしなかったかどうか、私は本当に気にしません。私は、しかし、考え好むそれはロード画面中に「時間浪費の未使用のオブジェクトのリサイクルに向けた取り組み」のではなく、ゲームプレイ時のことを。
Kröw

30

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


4
はい、それも私がやっていることです。たとえば、通常、収集できないインスタンスによってブロックされているメモリの量を知りたいため、Runtime.freeMemory()によって返される値は、System.gc()の後でのみ意味があります。もちろん、デバッグ/メモリプロファイリングでのみ使用され、本番環境では使用されません。
sleske 2009年

Nawは、他の多くのシナリオにも適しています。たとえば、ライフサイクルを認識する単一のパターンがあるとします。onStop()でインスタンスをnullにしている場合は、System.gc()を呼び出して支援することをお勧めします。
ポートフォリオ

26

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

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

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

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

ただし、への呼び出しSystem.gc()が理解できる場合はほとんどありません。たとえば、マイクロベンチマークについて考えてみましょう。誰も、マイクロベンチマークの途中でGCサイクルが発生することを望んでいません。そのため、各測定の間にGCサイクルをトリガーして、すべての測定が空のヒープから始まることを確認できます。


26

JavaではGCを制御できません-VMが決定します。私はケース全体を実行したことがないSystem.gc()ている必要。以来System.gc()コールは、単にVMがガベージコレクションを行うことを示唆していると、それはまた、完全なガベージコレクション(多世代ヒープ内の新旧世代)を行い、それが実際に発生する可能性がありますMORE CPUサイクルを必要以上に消費されます。

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


17

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

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


私のAndroidアプリケーションは常にOutOfMemoryExceptionをスローします。そのため、クラスのonDestroy関数でSystem.gc()を使用して、不要な参照とオブジェクトをすべて削除することを考えていました。それは良いアプローチ
ですか

2
@Sagar Devangaあなたが説明するように手動でGCを呼び出すことは助けにはならないでしょう。OOMをスローする前に、JVMはメモリを解放するためにガベージコレクションをすでに試みているでしょう
Scrubbie

10

System.gc()VMによって実装され、VMが行うことは実装固有です。たとえば、実装者は単に戻り、何も実行できません。

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


8

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

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


System.gc()が直接割り当てを収集するのに対し、JVMは通常(OOMをスローする前に)収集しないと言っていますか?それは間違っていると思うので。明示的なGCの後で割り当てが成功する唯一の理由は、追加の時間と、ファイナライザが解放されている(および直接割り当てられているオブジェクトを解放している)ヒープ内オブジェクトの可能性です。
エケス

Java 6の最新バージョンでは、allocateBufferのコードは常にOutOfMemoryErrorをスローする前にSystem.gc()を実行します。ファイナライズコードには、Cleanersダイレクトメモリが使用するショートカットがあります。つまり、これは遅すぎる可能性があるため、ファイナライザスレッドによって解放されません。それでも、ダイレクトメモリ領域を特に高速に作成している場合は、OOMEを取得できます。解決策は、それを行わず、可能な場合は直接メモリ領域を再利用することです。
Peter Lawrey

1
おかげで、これは私の経験のように聞こえます。だから私は答えが古いJavaバージョンに対してのみ正しいと思います。
eckes

5

ほとんどのJVMはGCを開始します(-XX:DiableExplicitGCおよび-XX:+ ExplicitGCInvokesConcurrentスイッチによって異なります)。しかし、仕様は、後でより良い実装を可能にするために、あまり明確に定義されていません。

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

内部的には、gcメソッドはRMIとNIOによって使用され、同期実行が必要です。これは現在、次のように議論されています。

バグ#5025281:System.gc()が同時(全世界ではない)フルコレクションをトリガーできるようにする


3

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

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

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


そのための時間があれば、JVMはgcを実行します。常にtrueとは限りません。JVMは、Edenメモリがいっぱいのときにgcを実行できます。
abdelmouheimen

2

通常、VMはOutOfMemoryExceptionをスローする前にガベージコレクションを自動的に実行するため、明示的な呼び出しを追加しても、パフォーマンスヒットがより早い時点に移動する場合を除き、役に立ちません。

しかし、それが関係しているのではないかと思った。ただし、効果があるかどうかはまだテストしていないため、わかりません。

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


2

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


2

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

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

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

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

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


2

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

GarbageCollectorMXBeanクラスがJava 7アップデート4で導入されたかどうかは、リリースノートで見つけることができなかったので100%わかりませんが、javaperformancetuning .comサイトで情報を見つけました


0

明示的なGCを実行するのが良い場合の具体的な例は思いつきません。

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

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


2
System.gc()を呼び出して、他の方法では閉じられないMappedByteBufferオブジェクトを閉じようとします。そのため、オブジェクトに対して 'close()'を呼び出しても、他のプロセスやファイルの切り捨てには使用できません。残念ながら、それでもまだ閉じているとは限りません。
Tim Cooper

0

Bruce EckelによるJavaでの思考に順応する、明示的なSystem.gc()呼び出しの1つの使用例は、ファイナライズ、つまりfinalizeメソッドの呼び出しを強制したい場合です。


注意:ファイナライズ実行を強制する独自の方法があります。(問題は実際にはファイナライザの実行ではなく、オブジェクトが参照されていないためにファイナライズできることを認識していることです)
eckes

-1

system.gcが機能している間、それは世界を停止します。ガベージコレクターがすべてのオブジェクトをスキャンして、削除する必要があるかどうかを確認できるように、すべてのレスポンが停止します。アプリケーションがWebプロジェクトの場合、GCが完了するまですべてのリクエストが停止します。これにより、Webプロジェクトがモニターで機能しなくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.