Javaのガベージコレクターとは何ですか?


103

私はJavaに不慣れで、Javaのガベージコレクターについて混乱しています。実際に何をするのか、いつ実行されるのか。Javaのガベージコレクターのプロパティのいくつかを説明してください。



10
良い本の章を読んで、1つの質問に対する答えから複雑な主題を理解することを期待する方がよい場合もあります。
Ian Ringrose

4
@Ianこれは同様の質問ですが、重複はしません。そして、その質問は宿題の悪臭を放ちます。
NullUserException

回答:


119

ガベージコレクタは、上で動作するプログラムであるJava仮想マシンもはやJavaアプリケーションで使用されていないオブジェクトを取り除きます。これは、自動メモリ管理の形式です。

典型的なJavaアプリケーションの実行中は、StringsやFiles などの新しいオブジェクトが作成されますが、一定の時間が経過すると、それらのオブジェクトは使用されなくなります。たとえば、次のコードを見てください。

for (File f : files) {
    String s = f.getName();
}

上記のコードでString sは、forループの各反復でが作成されています。つまり、すべての反復で、Stringオブジェクトを作成するために少しのメモリが割り当てられます。

コードに戻ると、単一の反復が実行されると、次の反復ではString、前の反復で作成されたオブジェクトがもう使用されていないことがわかります。このオブジェクトは「ガベージ」と見なされます。

やがて、大量のゴミが出始め、もう使われていないオブジェクトにはメモリが使われます。この状態が続くと、最終的にJava仮想マシンのスペースが足りなくなり、新しいオブジェクトが作成されます。

そこで、ガベージコレクターが介入します。

ガベージコレクターは、使用されなくなったオブジェクトを探し、それらを削除してメモリを解放し、他の新しいオブジェクトがそのメモリの一部を使用できるようにします。

Javaでは、メモリ管理はガベージコレクターによって処理されますが、Cなどの他の言語では、などの関数を使用して独自にメモリ管理を実行する必要がmallocありfreeます。メモリ管理は、間違いを犯しやすいものの1つであり、これがいわゆるメモリリーク(メモリが使用されなくなったときにメモリが解放されない場所)につながる可能性があります。

ガベージコレクションのような自動メモリ管理スキームにより、プログラマはメモリ管理の問題についてそれほど心配する必要がなくなり、開発に必要なアプリケーションの開発に集中できるようになります。


コンピューター上で実行されているJavaアプリケーションが2つのガベージコレクション機能を持っていると言うのは本当でしょうか。1つはJava仮想マシンです。そして、Windowsを実行する実際のマシン上に1つはありますか?(またはその他のOS)
Lealo 2017

いいえ、通常、JavaアプリケーションはJREが存在する場合にのみ実行されます。したがって、JVMのガベージコレクション機能のみが必要です。@Lealo
Am_I_Helpful

18

プログラムによって使用されなくなったオブジェクトに割り当てられたメモリを解放します。そのため、「ガベージ」という名前が付けられます。例えば:

public static Object otherMethod(Object obj) {
    return new Object();
}

public static void main(String[] args) {
    Object myObj = new Object();
    myObj = otherMethod(myObj);
    // ... more code ...  
}

これは非常に不自然であることがわかっていますが、ここで呼び出しotherMethod()た後、Object作成されたオリジナルは到達不能になります。これがガベージコレクションの「ガベージ」です。

Javaでは、GCが自動的に実行されていますが、明示的で、それを呼び出すことができますSystem.gc()し、しようとする主要なガベージコレクションを強制します。Pascal Thiventが指摘しているように、これを行う必要はありませんし、害があるかもしれません(この質問を参照)。

詳細については、ガベージコレクションチューニングガベージコレクション(Oracleから)に関するウィキペディアのエントリを参照してください。


1
AFAIK System.gc()はGCの実行を強制しません。
Itay Karo

1
適切なコード例の+1。myObj呼び出しotherMethodが行われる前にGCが破棄されることは完全に有効であることに注意してくださいmyObj
ビリーONeal

@イタリア私はそれが実装固有であると信じています。
NullUserException

2
私はを呼ぶべきではないと思いますSystem.gc()、GCを持つことのすべてのポイントはそれをする必要がないことです。
Pascal Thivent

エスケープ分析(en.wikipedia.org/wiki/Escape_analysis)を使用すると、JVMがこの例の最初の場所でオブジェクトを割り当てさえしない可能性があります。オブジェクトの作成全体を(理論的には)最適化することができます。もちろん実装依存。
mikera 2013

15

オブジェクトは、ライブスレッドまたは静的参照から到達できない場合、ガベージコレクションまたはGCの対象になります。

つまり、すべての参照がnullの場合、オブジェクトはガベージコレクションの対象になると言えます。循環依存関係は参照としてカウントされないため、オブジェクトAにオブジェクトBへの参照があり、オブジェクトBにオブジェクトAへの参照があり、他にライブ参照がない場合、オブジェクトAとBの両方がガベージコレクションの対象になります。


ガベージコレクションのヒープ生成-

Javaオブジェクトは、Javaでのガベージコレクションのために作成されHeapHeap3つの部分または世代に分割されます。これらは、ヒープのYoung(New)世代、Tenured(Old)世代、およびPerm Areaと呼ばれます。

Javaヒープスペース ニュージェネレーションはさらに、エデンスペースとして知られるサバイバー1とサバイバー2の3つの部分に分かれています。ヒープで最初に作成されたオブジェクトがエデン空間内の新しい世代で作成された後、その後のマイナーガベージコレクションの後でオブジェクトが存続すると、メジャーガベージコレクションがそのオブジェクトを古い世代または古い世代に移動する前に、サバイバー1に移動し、次にサバイバー2に移動します。

Javaヒープのパーマスペースは、JVMがクラスとメソッド、文字列プール、クラスレベルの詳細に関するメタデータを格納する場所です。

ガベージコレクションのヒープ生成

詳しくはこちらをご覧ください:ガベージコレクション


System.gc()またはRuntime.gc()メソッドを使用してリクエストを行うことはできますが、JVMにガベージコレクションを実行させることはできません。

java.lang.System

public static void gc() {
    Runtime.getRuntime().gc();  
}

java.lang.Runtime内

public native void gc();  // note native  method

マークアンドスイープアルゴリズム-

これは、ガベージコレクションで使用される最も一般的なアルゴリズムの1つです。ガベージコレクションアルゴリズムは、2つの基本的な操作を実行する必要があります。1つは、到達できないすべてのオブジェクトを検出できること、もう1つは、ガベージオブジェクトによって使用されているヒープスペースを再利用して、プログラムが再びスペースを利用できるようにすることです。

上記の操作は、マークアンドスイープアルゴリズムによって2つのフェーズで実行されます。

  1. マークフェーズ
  2. スイープフェーズ

詳細については、こちらをご覧ください- マークアンドスイープアルゴリズム


6

ガベージコレクターは、プログラムで不要になったオブジェクトは「ガベージ」であり、破棄できることを意味します。


6

ガベージコレクターは、参照されていないオブジェクトがメモリから解放されるようにするJREの一部です。
通常、アプリがメモリ不足になると実行されます。AFAIKは、オブジェクトと分離されたオブジェクトとの間のリンクが解放されることを表すグラフを保持しています。
世代にグループ化された現在のオブジェクトのパフォーマンスを節約するために、GCがオブジェクトをスキャンし、そのオブジェクトがまだ参照されていることを検出するたびに、1ずつインクリメントして(最大数の最大値、3または4と思います)、新しい世代が最初にスキャンされます(メモリ内のオブジェクトが最短であるほど、不要になる可能性が高い)したがって、GCが実行されるたびにすべてのオブジェクトがスキャンされるわけではない。詳細について
は、こちらをお読みください。


@quantumSoupはあなたはこれに積極的ですか?あるガベージコレクション(より高価なガベージコレクション)は、ヒープがいっぱいになったときにのみ発生すると思います。
パブロフェルナンデス

2
@quantumSoup-JREのGC実装によって異なります。多くの場合、GC 常に実行されません。代わりに、ヒープがいっぱいであるためにアプリがオブジェクトを割り当てることができないときに実行されます。最近のHotSpot JVMには並列GCが含まれていますが、デフォルトでは有効になっていません。
Stephen C

この回答はメカニズムに集中しすぎています。質問は「ガベージコレクターとは何か」ではなく、「ガベージコレクターはどのように動作するか」ではありませんでした
Billy ONeal

@quantum:-1を無効にしました。理由:学習、つまり、このページの目的ですよね?学ぶには間違いをする必要があります。過ちを罰すると、人々は学ばなくなる。その点については、同意していただければ幸いです。そして多分あなたはここで間違いをしました。
erikbwork

1
@erikb:そのロジックにより、反対投票はありません。そして、比較的悪い答えを取り除くために反対票が必要です。OPは明らかに初心者であり、GCの特定の内部動作は、尋ねられた質問にとって重要ではありません。この回答は、質問の答えにはなりません(別の質問に答えます)ので、反対票は完全に正当化されます。
Billy ONeal、

3

ガベージコレクターを使用すると、コンピューターは無限メモリを備えたコンピューターをシミュレートできます。残りは単なるメカニズムです。

これは、メモリのチャンクがコードからアクセスできなくなったことを検出し、それらのチャンクを空きストアに返すことによって行われます。

編集:はい、リンクはC#用ですが、C#とJavaはこの点で同一です。


実際には、JavaとC#のGCの違いについてSOに質問があります
。stackoverflow.com/ questions / 492703 / c

3

多くの人は、ガベージコレクションは死んだオブジェクトを収集して破棄すると考えています。
実際には、Javaガベージコレクションはその逆です。ライブオブジェクトが追跡され、その他はすべてゴミを指定します。

オブジェクトが使用されなくなると、ガベージコレクターは基になるメモリを再利用し、将来のオブジェクトの割り当てに再利用します。これは、明示的な削除がなく、オペレーティングシステムにメモリが戻されないことを意味します。使用されなくなったオブジェクトを判別するために、JVMはマークアンドスイープアルゴリズムと呼ばれるものを断続的に実行します。

詳細については、こちらを確認してください:http : //javabook.compuware.com/content/memory/how-garbage-collection-works.aspx


1

プログラマーではない人でも理解できる最も簡単な言葉で言えば、プログラムがデータを処理すると、そのデータの中間データとストレージスペース(変数、配列、特定のオブジェクトメタデータなど)が作成されます。

これらのオブジェクトが関数間または特定のサイズを超えてアクセスされると、中央のヒープから割り当てられます。次に、それらが不要になったときに、クリーンアップする必要があります。

これがどのように機能するかについて、いくつかの非常に良い記事がオンラインにありますので、私は非常に基本的な定義をカバーします。

GCは基本的にこのクリーンアップを行う関数です。これを行うには、アクティブなオブジェクトによって参照されていないテーブルエントリをクリアし、オブジェクトを効果的に削除します。その後、メモリをコピーして圧縮します。これは少し複雑ですが、アイデアはわかります。

大きな問題は、このプロセスの多くの場合、このプロセスを実行するためにJava VM全体を一時的に停止する必要があり、このプロセス全体が非常にプロセッサとメモリの帯域幅を大量に消費することです。GCのさまざまなオプションとそれぞれのチューニングオプションは、GCプロセス全体でこれらのさまざまな問題のバランスを取るように設計されています。


0

Java(および他の言語/プラットフォーム)のガベージコレクションは、Javaランタイム環境(JRE)が不要になったJavaオブジェクトのメモリを再利用するための方法です。簡単に言うと、JREは最初の起動時にオペレーティングシステム(O / S)に一定量のメモリを要求します。JREがアプリケーションを実行すると、そのメモリが使用されます。アプリケーションがそのメモリを使用して完了すると、JREの「ガベージコレクター」が現れ、既存のアプリケーションのさまざまな部分で使用するためにそのメモリを再利用します。JREの「ガベージコレクター」は、常に実行されているバックグラウンドタスクであり、システムがアイドル状態のときにガベージランを実行する時間を選択しようとします。

現実の世界の例えは、あなたの家に来て、あなたのリサイクル可能なゴミを拾うゴミの男性です...最終的には、自分や他の人々によって他の方法で再利用されます。


0

ガベージコレクターは、参照カウントマネージャーと見なすことができます。オブジェクトが作成され、その参照が変数に格納されている場合、その参照カウントは1ずつ増加します。実行中にその変数にNULLが割り当てられている場合。そのオブジェクトの参照カウントは減少します。そのため、オブジェクトの現在の参照カウントは0です。ガベージコレクターが実行されると、参照カウント0のオブジェクトがチェックされ、それに割り当てられていたリソースが解放されます。

ガベージコレクターの呼び出しは、ガベージコレクションポリシーによって制御されます。

ここでデータを取得できます。 http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html


1
参照カウントは、GCを実装するお粗末な方法の1つです。主要なJVM実装でこれを使用しているとは思いません。
NullUserException

0

ガベージコレクターはjvmのコンポーネントです。

これは、CPUが解放されたときにゴミを収集するために使用されます。

ここでガベージとは、メインプログラムのバックグラウンドで実行される未使用のオブジェクトを意味します

メインプログラムのステータスを監視します。


0

自動ガベージコレクションは、ヒープメモリを調べて、使用中のオブジェクトと使用されていないオブジェクトを識別し、未使用のオブジェクトを削除するプロセスです。使用中のオブジェクトまたは参照されるオブジェクトは、プログラムの一部がまだそのオブジェクトへのポインタを保持していることを意味します。未使用のオブジェクトまたは参照されていないオブジェクトは、プログラムのどの部分からも参照されなくなりました。そのため、参照されていないオブジェクトが使用していたメモリを解放できます。

Cのようなプログラミング言語では、メモリの割り当てと割り当て解除は手動のプロセスです。Javaでは、メモリの割り当てを解除するプロセスは、ガベージコレクターによって自動的に処理されます。理解を深めるためにリンクを確認してください。 http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html


0

ガベージコレクションとは、プログラムで到達できなくなったオブジェクトを削除することにより、ヒープ上のメモリを自動的に解放するプロセスを指します。ヒープは、フリーストアと呼ばれるメモリであり、Javaアプリケーションに割り当てられた未使用メモリの大きなプールを表します。


1
引用されていないテキストには引用形式を使用しないでください。引用されている場合は、ソースを引用する必要があります。
ローンの侯爵

0

ガベージコレクションの基本原則は、将来アクセスできないプログラム内のデータオブジェクトを見つけ、それらのオブジェクトが使用するリソースを再利用することです。https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29

メリット

1)ポインタへのポインタがまだある間にメモリの一部が解放され、それらのポインタの1つが逆参照されると発生するバグからの保存。https://en.wikipedia.org/wiki/Dangling_pointer

2)二重解放バグ。これは、プログラムがすでに解放されているメモリ領域を解放しようとしたときに発生し、おそらくすでに再度割り当てられています。

3)特定の種類のメモリリークが発生しないようにします。この場合、プログラムは、到達不能になったオブジェクトによって占有されているメモリを解放できず、メモリが使い果たされる可能性があります。

短所

1)追加のリソースの消費、パフォーマンスへの影響、プログラム実行のストールの可能性、および手動リソース管理との非互換性。プログラマが既にこの情報を知っている場合でも、ガベージコレクションは解放するメモリを決定する際にコンピューティングリソースを消費します。

2)実際にガーベッジが収集される瞬間は予測できない場合があり、その結果、セッション全体にストール(シフトの一時停止/メモリーの解放)が散在します。予測不能なストールは、リアルタイム環境、トランザクション処理、または対話型プログラムでは受け入れられない場合があります。


Oracleチュートリアル http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

ガベージコレクションは、使用中のオブジェクトと未使用のオブジェクトを識別し、未使用のオブジェクトを削除するプロセスです。

C、C ++などのプログラミング言語では、メモリの割り当てと解放は手動のプロセスです。

int * array = new int[size];
processArray(array); //do some work.
delete array; //Free memory

プロセスの最初のステップはマーキングと呼ばれます。ここで、ガベージコレクターは、使用中のメモリと使用されていないメモリを識別します。

ステップ2a。通常の削除では、参照されていないオブジェクトが削除され、参照されているオブジェクトと空き領域へのポインタが残ります。

パフォーマンスを改善するために、参照されていないオブジェクトを削除し、残りの参照されているオブジェクトも圧縮します。参照されるオブジェクトをまとめて保持したいので、新しいメモリを割り当てる方が速くなります。

前述のように、JVM内のすべてのオブジェクトにマークを付けて圧縮する必要があるのは非効率的です。割り当てられるオブジェクトが増えると、オブジェクトのリストが大きくなり、ガベージコレクション時間が長くなります。

このチュートリアルを読み続けると、GCがこの課題にどのように取り組むかがわかります。

要するに、ヒープには3つの領域があります。寿命の短いオブジェクトの場合はYoungGeneration、期間の長いオブジェクトの場合はOldGeneration、アプリケーションの寿命中に存在するオブジェクト(クラス、ライブラリなど)の場合はPermanentGenerationです。


0

オブジェクトは新しいオペレーターによって動的に割り当てられるため、これらのオブジェクトがどのように破棄され、ビジーなメモリがどのように解放されるかを確認できます。C ++などの他の言語では、手動で割り当てられたオブジェクトを削除演算子によって動的に解放する必要があります。Javaのアプローチは異なります。割り当て解除は自動的に処理されます。この手法は、ガベージコレクションと呼ばれます

これは次のように機能します。オブジェクトへの参照がない場合、このオブジェクトは不要であると見なされ、オブジェクトが占有しているメモリを取得できます。C ++のようにオブジェクトを明示的に破棄する必要はありません。プログラムの実行中にガベージコレクションが散発的に発生します。使用されなくなったオブジェクトが1つ以上あるため、単に発生するわけではありません。さらに、いくつかのJavaランタイム実装ではガベージコレクションへのアプローチが異なりますが、ほとんどのプログラマはプログラムを作成するときにこれについて心配する必要はありません。


-2

自動ガベージコレクションは、JVMが特定のデータポイントをメモリから削除または保持して、最終的に実行中のプログラムのためにスペースを解放するプロセスです。メモリは最初にヒープメモリに送信されます。つまり、ガベージコレクタ(GC)がその作業を行う場所であり、その後、終了または保持することが決定されます。Javaは、プログラマーが常に信頼できるとは限らないと想定しているため、不要と思われるアイテムを終了します。

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