23

うまくいけば、簡単な質問です。たとえば、循環リンク リストを見てみましょう。

class ListContainer
{
  private listContainer next;
  <..>

  public void setNext(listContainer next)
  {
    this.next = next;
  }
}

class List
{
  private listContainer entry;
  <..>
}

これは循環的にリンクされたリストであるため、単一の要素が追加されると、次の変数にそれ自体への参照が含まれます。リスト内の唯一の要素を削除する場合、entry は null に設定されます。ガベージ コレクターがメモリを解放するために ListContainer.next を null に設定する必要がありますか、それともそのような自己参照を自動的に処理しますか?

4

7 に答える 7

24

参照カウントのみに依存するガベージ コレクターは、一般に、このような自己参照構造の収集に失敗する可能性があります。これらの GC は、特定のオブジェクトが到達可能かどうかを計算するために、オブジェクトへの参照数のカウントに依存します。

非参照カウントのアプローチでは、より包括的な到達可能性テストを適用して、オブジェクトが収集される資格があるかどうかを判断します。これらのシステムは、常に到達可能であると想定されるオブジェクト (またはオブジェクトのセット) を定義します。このオブジェクト グラフから参照できるオブジェクトは、コレクションの対象外と見なされます。このオブジェクトから直接アクセスできないオブジェクトはアクセスできません。したがって、サイクルが到達可能性に影響を与えることはなく、収集することができます。

ガベージ コレクターのトレースに関するウィキペディアのページも参照してください。

于 2009-01-02T20:14:19.553 に答える
14

オブジェクトが死んでいるかどうかを判断するために参照のカウントに依存している場合、循環参照は (解決可能な) 問題です。参考までに、参照カウントを使用するJava実装はありません。新しい Sun JRE は、いくつかのタイプの GC を組み合わせて使用​​し、すべてマーク アンド スイープまたはコピーを使用していると思います。

一般的なガベージ コレクションの詳細についてはWikipediaを参照してください。Java GC に関するいくつかの記事は、たとえば、ここここにあります。

于 2009-01-02T19:57:25.190 に答える
7

これに対する実際の答えは、実装に依存します。Sun JVM は、ルート オブジェクト (スレッドなど) のセットを追跡し、ガベージ コレクションを実行する必要がある場合、それらから到達可能なオブジェクトを追跡して保存し、残りを破棄します。いくつかの最適化を考慮すると、実際にはそれよりも複雑になりますが、それが基本原則です。このバージョンは循環参照を気にしません: 生きているオブジェクトが死んでいるオブジェクトへの参照を保持していない限り、それは GC できます。

他の JVM は、参照カウントと呼ばれる方法を使用できます。オブジェクトへの参照が作成されると、一部のカウンターがインクリメントされ、参照がスコープ外になると、カウンターがデクリメントされます。カウンターがゼロになると、オブジェクトはファイナライズされ、ガベージ コレクションが行われます。ただし、このバージョンでは、ガベージ コレクションが行われない循環参照の可能性が考慮されています。安全策として、このような JVM の多くには、実際に死んでいるオブジェクトを特定するためのバックアップ メソッドが含まれており、自己参照を解決してヒープをデフラグするために定期的に実行されます。

于 2009-01-02T20:19:43.273 に答える
6

答えがないことはさておき (既存の答えで十分です)、GC に少しでも興味がある場合は、JVM ガベージ コレクション システムに関するホワイトペーパーをチェックしてみてください。(とにかく、JVM ガベージ コレクションをググってください)

使用されているいくつかの手法に驚き、「Eden」などの概念を読んだときに、Java と JVM が実際に C/C++ よりも高速であることに初めて気付きました。(C/C++ がオブジェクト/メモリ ブロックを解放するときはいつでも、コードが関与します... Java がオブジェクトを解放するとき、実際には何もしません。優れた OO コードでは、ほとんどのオブジェクトが作成されてすぐに解放されるため、これは驚くほど効率的です。)

最新の GC は非常に効率的である傾向があり、新しいオブジェクトとはかなり異なる方法で古いオブジェクトを管理し、GC を短く中途半端に、または長く完全に制御することができます。多くの GC オプションはコマンド ライン スイッチで管理できるため、実際にはすべての用語が実際に何を指しているのかを知っておくと便利です。

注: これが誤解を招くものであることに気付きました。C++ の STACK 割り当ては非常に高速です。私のポイントは、現在のルーチンが終了した後に存在できるオブジェクトを割り当てることでした (これはすべてのオブジェクトであるべきだと私は信じています。 OO で考えますが、C++ の速度ではこれは非現実的なものになる可能性があります)。

スタックに C++ クラスのみを割り当てる場合、その割り当ては少なくとも Java と同じくらい高速になります。

于 2009-01-02T22:38:51.480 に答える
4

Java は、到達できないオブジェクトを収集します。エントリへの参照が他にない場合は、エントリ自体への参照があっても収集されます。

于 2009-01-02T19:57:09.900 に答える
2

はい。:)

http://www.ibm.com/developerworks/java/library/j-jtp10283/をチェックしてください。

すべての JDK (Sun 製) には、「到達可能性」という概念があります。GC がオブジェクトに「到達」できない場合、そのオブジェクトは消えます。

これは「新しい」情報ではありません (回答者への最初の情報は素晴らしいです) が、リンクは役に立ち、簡潔であることは素晴らしいことです。:)

于 2009-01-02T22:18:23.500 に答える