How Garbage Collection Works

ガーベッジ コレクションを組み込んだ Java Memory Management は、この言語の最も優れた成果の 1 つです。 ガベージコレクターが自動的にメモリを再利用するため、開発者はメモリの割り当てと割り当て解除について明示的に心配することなく、新しいオブジェクトを作成することができます。 これにより、メモリリークやその他のメモリ関連の問題を排除しつつ、より少ない定型的なコードでより速い開発が可能になる。 少なくとも理論上は。

皮肉なことに、Java ガーベッジ コレクションは、あまりにも多くのオブジェクトを作成および削除して、うまく機能しすぎているようです。 ほとんどのメモリ管理の問題は解決されますが、多くの場合、深刻なパフォーマンスの問題を引き起こすという代償を払うことになります。 ガベージ コレクションをあらゆる状況に適応できるようにした結果、複雑で最適化しにくいシステムになってしまいました。 ガベージ コレクションについて理解するためには、まず、メモリ管理が Java 仮想マシン (JVM) でどのように動作するかを理解する必要があります。

How Java Garbage Collection Really Works

多くの人は、ガベージ コレクションが死んだオブジェクトを収集して破棄すると思っています。 実際には、Java ガーベッジ コレクションはその逆をやっています! 生きているオブジェクトは追跡され、それ以外はすべてゴミとして指定されます。

ヒープから始めましょう。ヒープとは、動的割り当てに使用されるメモリの領域です。 ほとんどの構成では、オペレーティング システムは、プログラムが実行されている間、JVM によって管理されるように、事前にヒープを割り振ります。

  • オブジェクトの作成は、オブジェクトごとにオペレーティング システムとのグローバルな同期が必要ないため、より高速になります。 アロケーションは単にメモリ配列の一部を要求し、オフセットポインタを前方に移動します (図 2.1 を参照)。 次の割り当てはこのオフセットから始まり、配列の次の部分を要求します。
  • オブジェクトがもはや使用されないとき、ガベージコレクターは基礎となるメモリを取り戻し、将来のオブジェクト割り当てにそれを再使用します。 これは、明示的な削除がなく、オペレーティング システムにメモリが返されないことを意味します。

新しいオブジェクトは、使用されるヒープの終わりに単に割り当てられる

図 2.1:

すべてのオブジェクトは、JVM によって管理されるヒープ領域上に割り振られます。 開発者が使用するすべての項目は、クラスオブジェクト、静的変数、およびコード自体も含めて、このように扱われます。 オブジェクトが参照されている限り、JVM はそれを生きていると見なします。 オブジェクトが参照されなくなり、アプリケーション・コードからアクセスできなくなると、ガベージ・コレクターはそれを取り除き、未使用のメモリを取り戻します。 ツリー内の最初の参照は何なのか?

ガーベッジ コレクションのルート – すべてのオブジェクト ツリーのソース

すべてのオブジェクト ツリーは、1 つ以上のルート オブジェクトを持っている必要があります。 アプリケーションがそれらのルートに到達できる限り、ツリー全体に到達することができます。 しかし、これらのルート オブジェクトはいつ到達可能とみなされるのでしょうか。 ガベージ コレクション ルート (GC ルート。図 2.2 参照) と呼ばれる特別なオブジェクトは常に到達可能で、それ自身のルートにガベージ コレクション ルートがあるオブジェクトも同様です。

Java には 4 種類の GC ルートがあります。 これは実オブジェクトの仮想参照ではないので、目に見えるものではありません。

  • アクティブな Java スレッドは、常にライブ オブジェクトと見なされ、したがって GC ルーツとなります。 これは、スレッド局所変数にとって特に重要です。
  • 静的変数は、それらのクラスによって参照されます。 この事実は、それらを事実上の GC ルートにします。 クラス自体は、参照されるすべての静的変数を削除するガベージコレクトされることができます。 これは、一般的にアプリケーションサーバー、OSGiコンテナまたはクラスローダーを使用するときに、特別な重要性があります。 関連する問題については、問題パターンのセクションで説明します。
  • JNI 参照は、ネイティブ コードが JNI 呼び出しの一部として作成した Java オブジェクトです。 JVM は、それがネイティブ コードによって参照されているかどうか分からないので、このように作成されたオブジェクトは特別に扱われます。
  • GC ルートは、それ自体が JVM によって参照されるオブジェクトであり、したがって、他のすべてのオブジェクトがガベージ コレクションされないように維持します。 GC ルートは、それ自体が JVM によって参照されるオブジェクトであり、したがって、他のすべてのオブジェクトがガベージ コレクションされないようにします。

    したがって、単純な Java アプリケーションには次の GC ルートがあります:

    • メイン メソッドのローカル変数
    • メイン スレッド
    • メイン クラスの静的変数

    ゴミをマークして掃除する

    どのオブジェクトがもはや使われていないかを判断するために、JVM は非常に適切にマークして掃除するアルゴリズムと呼ばれているものの間欠的な実行します。

    1. アルゴリズムは、GC のルートから始まるすべてのオブジェクト参照をトラバースし、見つかったすべてのオブジェクトを生存しているとマークします。 これは、単に空きメモリとしてマークされ、本質的に未使用のオブジェクトから解放されます。

    ガーベッジ コレクションは、古典的なメモリ リークの原因である、到達できないが削除されないメモリ内のオブジェクトを除去することを目的としています。 しかし、これは本来の意味でのメモリ リークに対してのみ機能します。 開発者が単に参照を解除するのを忘れたために、アプリケーションからまだ到達可能な未使用のオブジェクトが存在する可能性があります。 このようなオブジェクトは、ガベージコレクトすることができません。 さらに悪いことに、このような論理的なメモリリークは、どのソフトウェアでも検出できません(図2.3参照)。 どんなに優れた解析ソフトウェアでも、疑わしいオブジェクトを強調表示することしかできません。

    オブジェクトが GC ルートによって直接または間接的に参照されなくなると、それらは削除されます。 古典的なメモリー リークはありません。 解析ではメモリ リークを実際に識別することはできず、疑わしいオブジェクトを示唆することしかできません

    GlobalSource !

    コメントを残す

    メールアドレスが公開されることはありません。