Javaではガベージコレクションが自動化されています。しかしSystem.gc()
、コードを呼び出すと、その時点でJVMがガベージコレクションを実行するかどうかを判断できることを理解しました。これはどのように正確に機能しますか?JVMは、GCを検出したときに、GCを実行する(または実行しない)と正確にどの基準/パラメーターで判断しますSystem.gc()
か?
あなたのコードにこれを入れるのが良い場合の例はありますか?
Javaではガベージコレクションが自動化されています。しかしSystem.gc()
、コードを呼び出すと、その時点でJVMがガベージコレクションを実行するかどうかを判断できることを理解しました。これはどのように正確に機能しますか?JVMは、GCを検出したときに、GCを実行する(または実行しない)と正確にどの基準/パラメーターで判断しますSystem.gc()
か?
あなたのコードにこれを入れるのが良い場合の例はありますか?
回答:
実際には、通常はガベージコレクションを実行することを決定します。答えは、実行しているJVM、実行しているモード、使用しているガベージコレクションアルゴリズムなど、さまざまな要因によって異なります。
私はあなたのコードではそれに依存しません。JVMがOutOfMemoryErrorをスローしようとしている場合、System.gc()を呼び出しても停止しません。ガベージコレクターは、極端になる前にできる限り解放しようとするためです。これが実際に使用されているのを目にしたのは、ユーザーがクリックできるボタンに接続されているIDEでだけですが、それでもそれほど役に立ちません。
System.gc()
ビデオゲームの読み込み画面で使用します。その時点では、呼び出しが可能な限りすべてをクリアしたか、まったく何もしなかったかどうか、私は本当に気にしません。私は、しかし、考え好むそれはロード画面中に「時間浪費の未使用のオブジェクトのリサイクルに向けた取り組み」のではなく、ゲームプレイ時のことを。
System.gc()を呼び出すのが理にかなっていると考えることができる唯一の例は、メモリリークの可能性を検索するためにアプリケーションをプロファイリングするときです。メモリスナップショットを取得する直前に、プロファイラーがこのメソッドを呼び出すと思います。
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サイクルをトリガーして、すべての測定が空のヒープから始まることを確認できます。
JavaではGCを制御できません-VMが決定します。私はケース全体を実行したことがないSystem.gc()
ている必要。以来System.gc()
コールは、単にVMがガベージコレクションを行うことを示唆していると、それはまた、完全なガベージコレクション(多世代ヒープ内の新旧世代)を行い、それが実際に発生する可能性がありますMORE CPUサイクルを必要以上に消費されます。
場合によっては、アプリケーションが重いリフトが発生する前の次の数分間アイドル状態になることがわかっているため、今すぐ完全なコレクションを実行することをVMに提案することが理にかなっています。たとえば、アプリケーションの起動時に多くの一時オブジェクトを初期化した直後(つまり、情報のTONをキャッシュしただけで、1分間ほど多くのアクティビティを取得しないことがわかっています)。Eclipseの起動などのIDEを考えてみてください。初期化には多くのことを行うので、おそらく初期化の直後に、その時点で完全なgcを実行することは理にかなっています。
を呼び出す場合は、非常に注意する必要がありますSystem.gc()
。これを呼び出すと、不要なパフォーマンスの問題がアプリケーションに追加される可能性があり、実際にコレクションを実行することが保証されません。実際にはSystem.gc()
、java引数を介して明示的に無効にすることができます-XX:+DisableExplicitGC
。
ガベージコレクションの詳細については、Java HotSpot Garbage Collectionで入手できるドキュメントを一読することを強くお勧めします。
ダイレクトメモリバッファーを使用する場合、ダイレクトメモリが不足している場合でも、JVMはGCを実行しません。
呼び出しByteBuffer.allocateDirect()
てOutOfMemoryErrorが発生した場合は、GCを手動でトリガーした後、この呼び出しで問題ないことがわかります。
Cleaners
ダイレクトメモリが使用するショートカットがあります。つまり、これは遅すぎる可能性があるため、ファイナライザスレッドによって解放されません。それでも、ダイレクトメモリ領域を特に高速に作成している場合は、OOMEを取得できます。解決策は、それを行わず、可能な場合は直接メモリ領域を再利用することです。
ほとんどのJVMはGCを開始します(-XX:DiableExplicitGCおよび-XX:+ ExplicitGCInvokesConcurrentスイッチによって異なります)。しかし、仕様は、後でより良い実装を可能にするために、あまり明確に定義されていません。
仕様の明確化が必要:バグ#6668279:(仕様)System.gc()は、使用を推奨せず、動作を保証しないことを示す必要があります
内部的には、gcメソッドはRMIとNIOによって使用され、同期実行が必要です。これは現在、次のように議論されています。
Garbage Collection
良いではJava
、我々はデスクトップ/ノートPC /サーバにJavaでコーディングされたソフトウェアを実行している場合。System.gc()
またはRuntime.getRuntime().gc()
で呼び出すことができますJava
。
これらの呼び出しは何もしないことが保証されていることに注意してください。これらは、jvmがガベージコレクタを実行するための提案にすぎません。GCを実行するかどうかに関係なく、JVMに依存します。つまり、簡単に言えば、いつ実行されるかはわかりません。より長い答え:時間がある場合、JVMはgcを実行します。
同じことがAndroidにも当てはまると思います。ただし、これによりシステムの速度が低下する可能性があります。
通常、VMはOutOfMemoryExceptionをスローする前にガベージコレクションを自動的に実行するため、明示的な呼び出しを追加しても、パフォーマンスヒットがより早い時点に移動する場合を除き、役に立ちません。
しかし、それが関係しているのではないかと思った。ただし、効果があるかどうかはまだテストしていないため、わかりません。
ファイルをメモリマップするとき、十分な大きさのメモリブロックが利用できない場合、map()呼び出しはIOExceptionをスローすると思います。map()ファイルの直前のガベージコレクションは、それを防ぐのに役立つと思います。どう思いますか?
時間をかけてさまざまなガベージコレクション設定をテストすることについては、多くのことが言われていますが、前述のように、通常はそうすることは役に立ちません。
私は現在、メモリ制限のある環境と比較的大量のデータを含むプロジェクトに取り組んでいます-私の環境をその限界まで押し上げるいくつかの大きなデータがあり、メモリ使用量を下げることができたとしても理論的には問題なく動作するはずですが、ヒープスペースエラーが発生します。詳細なGCオプションは、ガベージコレクションをしようとしているが、役に立たないことを示しています。デバッガーでSystem.gc()を実行して、十分な量のメモリが利用できることを確認できます。あまり多くはありませんが、十分です。
その結果、私のアプリケーションがSystem.gc()を呼び出すのは、データの処理に必要な大きなバッファーが割り当てられるコードのセグメントに入るときだけであり、利用可能な空きメモリのテストで、それを持っていることが保証されています。特に、少なくとも300MBが静的データで占有されている1GBの環境を調べています。非静的データの大部分は実行に関連しており、処理中のデータが少なくとも100-200 MBの場合は例外です。起源。それはすべて自動データ変換プロセスの一部であるため、データはすべて長期的には比較的短期間存在します。
残念ながら、ガベージコレクターを調整するためのさまざまなオプションに関する情報は利用できますが、それは主に実験的なプロセスであり、これらの特定の状況を処理する方法を理解するために必要な下位レベルの詳細は簡単には取得できません。
これらすべてについて、System.gc()を使用していても、コマンドラインパラメーターを使用して調整を続け、アプリケーションの全体的な処理時間を、かなりの量で改善できましたが、より大きなデータブロックを操作することで生じる障害物。そうは言っても、System.gc()はツールです....非常に信頼性の低いツールであり、その使用方法に注意しないと、それが頻繁に機能しないことが望まれます。
System.gc()
が呼び出されたかどうかを知りたい場合は、新しいJava 7 update 4を使用して、JVMがガベージコレクションを実行したときに通知を受け取ることができます。
GarbageCollectorMXBeanクラスがJava 7アップデート4で導入されたかどうかは、リリースノートで見つけることができなかったので100%わかりませんが、javaperformancetuning .comサイトで情報を見つけました
明示的なGCを実行するのが良い場合の具体的な例は思いつきません。
一般的に、明示的なGCは完全なコレクションをトリガーするため、明示的なGCを実行すると、実際よりも害が大きくなる可能性があります。この明示的なgcが繰り返し呼び出されると、フルGCの実行に多くの時間が費やされるため、アプリケーションが遅くなる可能性があります。
または、ヒープアナライザーでヒープを調べて、ライブラリコンポーネントが明示的なGCを呼び出していると思われる場合は、gc = -XX:+ DisableExplicitGCをJVMパラメーターに追加してオフにすることができます。