3

呼び出すだけでJavaでガベージコレクションを実行できますがSystem.gc()、これによってアプリケーションが「停止」することがあります。このようにガベージコレクションを行い、ストールを回避するのは悪い考えですか。

new Thread(new Runnable() {
   public void run() { 
      System.gc(); 
   }
}).start();

それとも、これはさらに多くの問題につながる可能性がありますか?

4

6 に答える 6

15

まず最初に:GCを明示的に呼び出さないでください

あなたがそれについて非常に正当な理由がある場合を除いて。そして、あなたがそう思ったとしても、おそらくそうではないでしょう。

GCはそれが何をしているのかを知っています(ほとんどの場合...)

あなたが読み続けているなら、それがいつ収集されるべきかを決定するよりもはるかに賢い可能性が非常に高いとしても、GCをいじくり回そうとする本当に素晴らしい(おそらくねじれているとはいえ)理由があると思いますメモリー。また、明示的に呼び出すと、混乱してヒューリスティックが台無しになるため、以前よりも賢くなくなることに注意してください。あなたがそれを裏切ろうとしたからです。

GCはあなたが言うことを常に気にするわけではありません

非常に正当な理由でこれを行う場合、または可能な限り最高のメモリ状態で集中的なコードセクションを開始することを本当に確認したい場合は、これがおそらく機能しないことを知っておく必要がありますSystem.gc()そのJavadoc 強調鉱山で言及されているように、行われるガベージコレクション:

gcメソッドを呼び出すと、Java仮想マシンが未使用のオブジェクトのリサイクルに労力を費やしていることがわかります

その他の推奨事項

ハントダウンアンドキル(悪い)明示的GC

  • オンにして-XX:+DisableExplicitGC(JVMがサポートしている場合)、危害を加えるというクレイジーな呼び出しを防ぎます(コメントのFredrikへのクレジット)
  • お気に入りのIDEを使用するかgrep、への呼び出しSystem.gc()とそれに相当するものを探して、それらを取り除きます。

別の方法を見つける

他の有用な提案(sの使用など)については、 Grooveekの回答を参照してくださいWeakReference

他のGCを試して、アプリに合わせてVMを微調整します

ユースケースによっては、CMC、G1、ParallelGCなどの他のGC実装を試すことが役立つ場合があります。「ストール」を回避したい場合は、最新のJava SEで導入されて以来、G1で非常に良い結果が得られています。 6つの更新とJava7のリリース以降、集中的なエンタープライズアプリケーションを長期間実行します。

JVMチューニングは非常に複雑な技術であることに注意してください。

参考文献

詳細については、これらをめくってください。

*注意して使用してください:完全に最新ではない場合があり、すべてを文書化しておらず、多くの実験的な機能、またはHotSpotのみの機能をリストしています。

于 2011-05-31T20:54:35.390 に答える
3

はい、ほとんどの場合、System.gc()を呼び出すことは非常に悪い考えです。例外はありますが、それらはほとんどありません。GC環境でパフォーマンスを損なうようなことをしていないことを確認し、gcがどのように機能するかを調べて理解することは、自分で処理するよりも、時間をかけて行う方がよいでしょう。 System.gc()を明示的に呼び出します。

于 2011-05-31T20:56:24.973 に答える
2

@haylem Answerの明快さと力に勝るものはありません、ごめんなさい。しかし、Javaでメモリを管理するための(より良い)方法はたくさんあることを付け加えておきます。たとえば、WeakHashMapのように、 WeakReferenceとこれらを処理するコレクションがあります。javadocによると、GCへの明示的な呼び出しはそうではありませんが、これらはメモリを処理する決定論的な方法です。

Calling the gc method suggests that the Java Virtual Machine expend effort toward 
recycling unused objects in order to make the memory they currently occupy available 
for quick reuse. When control returns from the method call, the Java Virtual Machine 
has made a best effort to reclaim space from all discarded objects.
于 2011-05-31T21:10:19.680 に答える
0

これまでにすでに述べたことは別として、1つの重要な詳細を悲しいことに見逃しているため、アイデア全体にひどい欠陥があります。

フルGCの実行中は、アプリケーションが停止します。(少なくとも現在、最新のHotspot VMで-そして他に何を使用しますか?)

ホットスポットにはマークとスイープの同時実装があります(ただし、デフォルトではafaikはアクティブ化されていません)が、余分なオーバーヘッドが発生し、スイープを実行する前にすべてのスレッドを停止する必要があります。したがって、基本的にどのスレッドからSystem.gc()を実行するかは重要ではありません。VMは、すべてのスレッドが安全なポイントに到達するのを待機し、それらを停止してから収集を実行します。したがって、スレッドを使用することはまったく役に立ちません。

于 2011-05-31T21:14:24.730 に答える
0

一般に、ガベージコレクターを明示的に呼び出すことは推奨されないことに完全に同意します。アプリケーションが数秒、場合によっては数分間停止する可能性があります。これは通常、バックグラウンドサービスを扱っている場合は問題になりませんが、ユーザーに公開されると、ユーザーのエクスペリエンスが低下します。

ただし、これを実行したい場合は極端な場合があります。メモリが非常に不足していて、アプリケーションがクラッシュする可能性がある場合です。しかし、これらの状況を回避するために、アプリケーションの設計と実装で多くのことができます。

メモリの再収集とメモリリークの回避に関して私が気に入っているJavaの機能の1つは、WeakReferenceオブジェクトです。彼らはあなたの友達です。

于 2011-05-31T21:16:22.323 に答える
0

他の人が言っているように、電話System.gc()は通常間違いです。(常にではありませ...)

呼び出しが有益である可能性が高いこれらのまれなユースケースの1つがあると仮定すると、考慮すべき2つのケースがあります。System.gc()

  • JVMが従来の「stoptheworld」コレクターを使用している場合、それを別のスレッドで実行しても違いはありません。GCは、その間、すべてのアプリケーションスレッドを停止します。

  • JVMが並行コレクターを実行している場合は、別のスレッドで実行することを勧めします。すべてのコレクターにすべてのスレッドが停止するフェーズがあることは事実ですが、呼び出しは「Java仮想マシンがすべての破棄されたオブジェクトからスペースを再利用するために最善を尽くした」System.gc()後に戻ると文書化されています。したがって、別のスレッドで実行すると、現在のスレッドが別のことを実行できるようになります。ただし、それぞれが呼び出す複数のスレッドを起動しないように注意する必要があります。つまり、スレッドの起動を担当するコードは、以前のGCスレッドを追跡する必要があります。System.gc()

于 2011-05-31T23:37:55.207 に答える