web-dev-qa-db-ja.com

Javaガベージコレクタ-いつ収集しますか?

ガベージコレクターが実際に収集するタイミングを決定するのは何ですか?それは、特定の時間の後、または特定の量のメモリが使い果たされた後に発生しますか?または、他の要因がありますか?

46
nalo

実行する時間であると判断したときに実行されます。世代別ガベージコレクタの一般的な戦略は、ジェネレーション0メモリの割り当てが失敗したときにコレクタを実行することです。つまり、メモリの小さなブロックを割り当てるたびに(大きなブロックは通常「古い」世代に直接配置されます)、システムはgen-0ヒープに十分な空き領域があるかどうかをチェックし、ない場合は実行しますGCが割り当てを成功させるためにスペースを解放します。次に、古いデータはgen-1ヒープに移動され、そこにスペースがなくなると、GCはそのコレクションを実行し、そこに最も長く存在していたデータをgen-2ヒープにアップグレードします。したがって、GCは単に「実行」されるわけではありません。 gen-0ヒープでのみ実行される可能性があります(ほとんどのコレクションはそれを実行します)か、大量のメモリを解放する必要がある場合はすべての世代をチェックします(これはかなりまれにしか必要ありません)。

しかし、これはonly戦略とはほど遠いものです。並行GCはバックグラウンドで実行され、プログラムの実行中にクリーンアップされます。一部のGCは、すべてのメモリ割り当ての一部として実行される場合があります。インクリメンタルコレクターがそれを実行し、メモリ割り当てごとにいくつかのオブジェクトをスキャンします。

ガベージコレクターの全体的なポイントは、ユーザーからの入力を必要とせずに、そのことを実行するだけであるということです。したがって、一般に、いつ実行されるかを予測することはできませんし、予測すべきではありません。

Suns JVMはそれほど前に世代別GCを獲得したとは思いません(v1.6かもしれませんか?長い間Javaをコーディングしていないので、これについてはよくわかりませんが、新しいバージョンのセールスポイントの1つは「世代別GC」でした。特に、。

他のJVMはもちろん、好きな戦略を自由に選択できます。

EDIT:Javaと世代別GCに関する上記の部分は正しくありません。詳細については、以下を参照してください。

1.0および1.1仮想マシンは、マークスイープコレクターを使用しました。これは、ガベージコレクション後にヒープを断片化する可能性がありました。 Java 1.2以降、仮想マシンは世代別コレクターに切り替わりました。これは、より優れた最適化動作を備えています( Javaの理論と実践:ガベージコレクションとパフォーマンス を参照)。

したがって、Javaには実際に世代別GCがあります。 Java 6の新機能は、Java 6u14で利用可能なGarbage-Firstガベージコレクター(G1)です。 1.6.0_14のリリースを主張する記事デフォルトでは有効になっていません。パラレルコレクタは依然としてデフォルトのGCであり、一般的な家庭での使用に最も効率的なGCです。 G1は、並行コレクターの代替となることを目的としています。より予測可能になるように設計されており、メモリ領域の設計により高速な割り当てを可能にします。

28
jalf
  • プログラムJITのコンパイル方法に依存します。
  • 外部からはいつ実行されるかを明確に伝えることはできません。
  • 特定のGCに依存するアルゴリズムに従います。
  • Java仮想マシンは、Windowsのデフォルトが4GBの場合、仮想メモリを使用してクライアントマシンで実行されます。また、その特定の時間にその空き仮想メモリに依存します。

この小さなプログラムを試して、GCの動作を確認できます。

public class GCTest {

   final int NELEMS = 50000;

   void eatMemory() {

      int[] intArray = new int[NELEMS];

      for (int i=0; i<NELEMS; i++) {
        intArray[i] = i;
      }

   }

   public static void main (String[] args) {

      GCTest gct = new GCTest();

      // Step 1: get a Runtime object
      Runtime r = Runtime.getRuntime();

      // Step 2: determine the current amount of free memory
      long freeMem = r.freeMemory();
      System.out.println("free memory before creating array: " + freeMem);

      // Step 3: consume some memory
      gct.eatMemory();

      // Step 4: determine amount of memory left after consumption
      freeMem = r.freeMemory();
      System.out.println("free memory after creating array:  " + freeMem);

      // Step 5: run the garbage collector, then check freeMemory
      r.gc();
      freeMem = r.freeMemory();
      System.out.println("free memory after running gc():    " + freeMem);
   }
}

可能性のある出力-あなたのケースでは異なる場合があります

free memory before creating array: 4054912
free memory after creating array:  3852496
free memory after running gc():    4064184

このリンクを確認してください http://www.devdaily.com/Java/edu/pj/pj010008/

7
Xinus

それは、実際に使用しているガベージコレクタ、その調整方法、および非常に多くの入力に大きく依存します。

HotSpot Garbage Collector(Javaに付属する一般的なもの)の概要と調整方法については、 this link

5
tschaible

JVMに実行に必要なメモリスペースがない場合、ガベージコレクタが実行されて不要なオブジェクトが削除され、JVMにメモリが割り当てられます。

不要なオブジェクトとは、参照(アドレス)を持たないオブジェクトです。

ガベージコレクターに適格なオブジェクトには、主に4つのポイントがあります。

  1. ヌル参照

    オブジェクトの参照変数に値としてnullが割り当てられている場合、ガベージコレクターはオブジェクトを削除できます。

        A a = new A();
        a = null;
    
  2. 再割り当て

    オブジェクトの参照変数に別のオブジェクトが割り当てられている場合、古い参照オブジェクトはガベージコレクターによって削除できます。

      A a = new A(100);
      a =new A(200);
    
  3. ローカルスコープ

    オブジェクトがブロック内で作成された場合、そのオブジェクトはそのブロック外のガベージコレクターに適格です。

      if(condition){
    
         A a = new A();
    
      }
    
  4. 分離

    オブジェクトは別のオブジェクトを参照できますが、スタック内のこれらのオブジェクトには少なくとも1つの参照(アドレス)変数が必要です。そうでない場合、これらのオブジェクトはすべてガベージコレクターの対象となります。

          class A{
                A r;
                A(int i){
                 //something   
               }
          } 
    
          A a1 = new A(100);
          a1.r = new A(101);
          a1.r.r = new A(102);
          a1.r.r.r = a1;
    
          a1  = null //all ojects are eligible to garbage collector  
    
2
Nisal Edu

これは、実際のJVMとそれが何を選択するかに完全に依存しており、基本的にプログラマーの手に負えません。 Greybearded die-hardの専門家may JVMの方がよく知っていることを伝えたいのですが、単なる人間にとっては、これは黒魔術と考えるべきです。

プログラムがオブジェクトを作成および破棄する速度に追いつくことができるかどうかは、あなたが心配する必要があります。そうでない場合、グローバルクリーンアップが発生している間、wholeプログラムは停止します。これは非常に悪い応答時間になりますが、最新のコンピューター上の最新のJVMではめったに起こりません。

プログラムで何がいつ起こるかについて興味がある場合は、Java 6 JDKの最新バージョンの「jvisualvm」ツールを調べてください。

ガベージコレクターは、リソースが必要なときに実行され、定期的にCPUを収集に使用するのに適した時期を伝えることで、 System.gc() を使用して影響を与えることができます

たとえば、リソースを割り当てるオブジェクトinit()メソッドと、それらのリソースを明示的にクリーンアップし、参照をnullにするcleanup()メソッドを指定することで、参照を明示的にnullにすることで、ガベージコレクターを支援できます。自分で参照をnullにすることで、ガベージコレクターがルートへのパスを増やす必要があるオブジェクトのクラスターを見つける必要がなくなります。

1
rsp