2011-01-24 13 views
14

我々は強制することはできませんと言われているgarbage collectionプロセスは、Javaで。
結局のところ、デーモンスレッドです。明示的にSystem.gc()を呼び出しますか?

しかし、まだ時々、System.gc();関数を明示的に呼び出すのはなぜですか?
それを呼び出す価値はありますか?プロとコンは何ですか?
多くの状況で役に立たない場合、なぜこのメソッドはJavaでは非推奨ではありませんか?

PS:例と説明が

答えて

8

私の意見では、System.gc()メソッドを考えるのは、ガベージコレクションを実行するVMのヒントです。それは、人々が実行していると思う「最適化」の大部分のように、通常はシステムが単独で処理することをお勧めします。システムは進化しています。また、開発者が実際によく知っているケースもあります。そのユースケースはおそらくアセンブラでコードが書かれている理由とよく似ています(ほとんどの場合、コンパイラはいくつかの例では(または少数の開発者で)、人間は実際にはより効率的なコードを書くことができます)。

過去にその存在を正当化するために使用されてきた例の1つは、多数のオブジェクトが割り当てられ、開発者が使用されなくなる瞬間を知っている場合です。その場合、GCよりもメモリ使用率に関する情報が多くなる場合があります(少なくともそれを実現する前に)。また、再利用されるメモリ量が重要なので、実行することをお勧めします。

6

Q有用であろう:私たちはにSystem.gc(呼び出す理由)。 は明示的に機能しますか?

A:誰かが悪いコードを書いているためです。

私は、ほとんどの人はあなたがコール明示的System.gc()べきではないと同意するだろうと思います。

システムが想定通りにメモリを管理できるようにします。パフォーマンスのためにそれに依存しているコードは、おそらく破損している可能性があります。また、JVMはあなたの要求を完全に無視することができます。

あなたはより多くの情報が必要な場合、私は答えを読んでお勧めしたい:

java - why is it a bad practice to call System.gc?

+0

はい。それは、HFJが提案したものです。しかし、本当に彼らの答えを納得させることはできませんでした。 –

8

あなたの質問の半分に答え:それは価値がありますか?いいえ、強制できないからです。

ガベージコレクタを実行します。このメソッドを呼び出すと、Java仮想マシンは、現在占有しているメモリをすばやく再利用できるようにするために、未使用オブジェクトのリサイクルに努力していることが示唆されます。

「これは試してみることができますが、私たちは両方の結果を知っています」とほぼEULA-Englishです。 :)

さらに、アプリケーションサーバーでは、-XX:-DisableExplicitGCコマンドラインオプションを使用して無効にすることができます。

それではポイントは何ですか?さて、ヒープ上で使用可能な空きメモリの量を表示するようなアプリケーションや、ディスプレイをリフレッシュする前に、System.gc();を呼び出すのが適度に便利なアプリケーションもあります。

+0

System.gc()は非常に高価な呼び出しです。 「メソッド呼び出しから制御が返ってくると、Java仮想マシンはすべての破棄されたオブジェクトから空間を再利用するために最善の努力をしました。 – RecursiveExceptionException

+1

これは、健康的なライフスタイルは働くことが保証されていないので価値がないと言っているようなものです。環境を制御する場合は、環境が動作することを確認することができます。そこにある 'System.gc()'の適切な使用よりもずっと多くの誤用がありますが、これは役に立たないものではありません。 – maaartinus

0

ここではどのバージョンのJavaについて説明していますか? 6では、私は決してそれを明示的に呼ぶつもりはない。一般的なルールとして、ガベージコレクタは、リソースをクリーンアップするのに最適な時期を知るのに十分であり、十分な設定可能なVMオプションを持っています。私は確かにそれをコードで呼び出す必要性を感じなかったし、あなたが本当に奇妙なこと(またはリソースの使用状況を示す)をしない限り、そうでない方がいいと言います。あなたがそれを呼び出す必要があると感じているなら、あなたは何か悪いか悪いことをどこかでやったと言います。

私たちがJava 1.4以前で作業することについて話しているのであれば、時には援助を必要としていることがわかります。 (申し訳ありませんが)手を加える例はありませんが、私は最終的に蹴ることに決めたときに恐ろしい遅れを避けるためにヒントを投げ掛ける必要があることを覚えています.6に同じコードを付けて、問題はなくなり、

もちろん、System.gc()に電話をしているときに、実際に行っているのは、ガベージコレクタを実行するのに適しているVMに提案することだけです。これは実際には意味するものではなく、完全に有効なVM実装が完全に無視されるという単なる提案です。実際にはこれらの呼び出しを意味するDisableExplicitGCオプションもありますは影響を受けません(本番環境では多くのコードがこのオプションで実行されます)。

はい、コードではまだ使用されていますが大部分の時間は、まったく良い練習ではありません。

3

()にSystem.gcを呼び出すときに、いくつかの例がありますが便利です:

  • あなたは、いくつかのベンチマークを実行しようとしているので、あなたが明確に定義された状態で起動する必要があります。
  • あなたはいくらかの重い負荷を期待しており、可能な限り良好な準備をしたいと考えています。
  • 複数のサーバーがあり、定期的にGCをスケジューリングすることによってポーズを避けたい場合は、定期的にlike hereを実行します。

もっと多くのユースケースがあるかもしれませんが、すぐに必要と思われるものは何もありません。たいていの場合、その作業を途中でやり直すほうがよいでしょう。

+1

私は2番目のものに同意しません。 "重い"負荷を起動すると、一般にJVMはこれを実現するのに十分であり、GCは適切なものになります。 – berry120

+0

JVMが事前に知ることができない重大な負荷を開始する前に*行うことを意味します。あなたが忙しい一日を過ごすことを期待するときは、すべての仕事を事前にするのと同じです。 – maaartinus

+0

@ berry120あなたが確かにそれを駆り立てたら、若い世代(Sunのホットスポット上)を空にすることができます。一般に、マルチスレッド環境でGCを呼び出すことは、Java開発者が喜んで残した修正の問題を除いて、決して推奨されません。 – bestsss

-1
It is said that we cannot force the garbage collection process in java. 

これはまったく間違っています。

いくつかのアプリケーションは定期的にそれを行い、一部のボタンでは光沢のあるボタンをクリックすることもできます。 GCを実行します。言い換えれば、GCがトリガーするGCを「示唆」していませんが、本当にGCを強制します。

信念は一般的で間違っています。

Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

+5

ガベージコレクタはJVM仕様では実際には必要ないため、ジェネリックJVMにガベージコレクションを強制することはできません。 – ILMTitan

+1

"メソッド呼び出しから制御が返ってくると、Java仮想マシン**は破棄されたすべてのオブジェクトから空間**を再利用するために最善を尽くしました。投票が下がる理由はなく、GCがないJVMも最善の努力をしています。 – maaartinus

+0

@ILMTitan:それでは、jvmtiインストルメンテーションを許可し、その文書化されたコールをサポートするVMで稼働しているJavaプログラムの99%を推測するのは良いことだと思う) – SyntaxT3rr0r

2

お答えするつもりはない:どのようなあまり人気のあることは、ここで私の6回upvoted質問にユニークな(そして非常にあいまい)な答えで示すように、あなたが実際に、そのようGCをトリガーする方法として知識であります質問はガベージコレクタを明示的に呼び出すことは悪い、悪い習慣ですが、Javaのコードの中にはファイナライズに依存しているものもあります。それを呼び出すことは、いくつかのプロファイリングのシナリオにおいても有用である。 標準JVMはSystem.gc()を無視しません。確かに、それは無効にすることができます。しかし、ガベージコレクタが外部リソースへのJava参照を管理するメモリを除いて、必要になる場合があります。ここ

はjava.nio.Bitsからいくつかのコードが確定したが、実際に実行(または未遂実行)するために睡眠が必要である

static void reserveMemory(long size) { 

    synchronized (Bits.class) { 
     if (!memoryLimitSet && VM.isBooted()) { 
      maxMemory = VM.maxDirectMemory(); 
      memoryLimitSet = true; 
     } 
     if (size <= maxMemory - reservedMemory) { 
      reservedMemory += size; 
      return; 
     } 
    } 

    System.gc(); 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException x) { 
     // Restore interrupt status 
     Thread.currentThread().interrupt(); 
    } 
    synchronized (Bits.class) { 
     if (reservedMemory + size > maxMemory) 
      throw new OutOfMemoryError("Direct buffer memory"); 
     reservedMemory += size; 
    } 

で、クリーナーは、通常、優先度の高いファイナライザスレッド上でファーストトラックを持っています。

0

明示的には、私たちはJVMを使用してゴミを掃除することを提案していますが、それはどうかにかかわらずJVMに任されており、System.gc()が発生したときに調べる基準をさらに課しています。基準が続く場合、それは動作する。そうでなければ

関連する問題