1

親オブジェクトの場合、別のオブジェクトのメンバーであるオブジェクトはガベージ コレクションの対象になりますか? たとえば、次のシナリオを想像してみましょう。

MyClass_1 のコード:

public class MyClass_1 {

    // Member object
    private MyClass_2 myClass_2;

    // Getter
    public MyClass_2 getMyClass_2() {
        return this.myClass_2;
    }

    // Setter
    public void setMyClass_2(MyClass_2 myClass_2) {
        this.myClass_2 = myClass_2;
    }
}

MyClass_2 のコード:

public class MyClass_2 {

    // Member object
    private MyClass_3 myClass_3;

    // Getter
    public MyClass_3 getMyClass_3() {
        return this.myClass_3;
    }

    // Setter
    public void setMyClass_3(MyClass_3 myClass_3) {
        this.myClass_3 = myClass_3;
    }
}

さて、これで完了です (MyClass_3 のコードは関係ありません)。

// Instantiation of one root object
MyClass_1 object_1 = new MyClass_1();

// Composition of two more objects
object_1.setMyClass_2(new MyClass_2());
object_1.getMyClass_2().setMyClass_3(new MyClass_3());

// And now...
object_1 = null;

確かに、この時点でobject_1 は Garbage Collectable ですが、object_2andはobject_3どうですか? メモリリークを避けるためにこれを行う必要がありますか?

object_1.getMyClass_2().setMyClass_3(null);
object_1.setMyClass_2(null);
object_1 = null;

それとも、JVM はそのリファレンス リリースを自動的に行いますか? 手動で行う必要がある場合、この目的で finalize() に頼ることはできますか?

4

2 に答える 2

5

これは孤立した島の典型的な例です。

はい.. null とマークされたすべてのオブジェクトとオブジェクト アイランド (オブジェクトが相互に参照している)。しかし、それらのどれにも到達できません)ガベージコレクションを取得します。

ガベージ コレクションの「孤立した島」に関するこの素敵な投稿を参照してください。

この場合、My_class2 と My_class3 を明示的に null に設定する必要はありません。親が null になると、GC はそれらもリサイクルします。

ファイナライズは、ガベージ コレクションを行う方法ではありません。基本的に finalize は、そのクラスのオブジェクトがガベージ コレクションされているときに、何かを行う機会を与えます。ただし、クリーンアップのために finalize メソッドに依存しないでください。オブジェクトがガベージ コレクションされず、finalize が呼び出されない可能性があるためです。

finalize の詳細を見るJava で finalize() メソッドが呼び出されるのはいつですか?

于 2013-09-13T18:39:10.880 に答える
2

オブジェクトがいつガベージ コレクションされるかを理解するには、オブジェクトがどのように割り当てられるかについて少し理解する必要があります。

すべてのプログラムには 2 つのメモリ部分があります。スタックヒープ。_ プログラムが実行されると、新しい関数またはメソッドに入ります。これにより、新しいスコープが作成されます。新しいスコープが作成されるたびに、対応する新しい「フレーム」がスタックの「トップ」に配置されます。このフレームには、そのスコープで使用されているすべての変数への参照があります。

newキーワード ( )などを介してオブジェクトが作成されると、MyObject obj = new MyObject();そのオブジェクトが占有するメモリの一部がヒープに確保されます。現在のスタック フレームは、オブジェクトが存在するヒープ内の場所への参照を持ちます。

そのオブジェクトは、明らかに、ヒープ上の他のオブジェクトへの参照を持っている可能性があります。プログラムがこれらのオブジェクトに到達する方法を知る方法は、スタック上の参照からヒープ上の最初のオブジェクトに移動し、次に直接または間接的に接続されている他のオブジェクトに移動することです。これらのオブジェクトはすべてヒープ上にあります。

スタック フレームがアンロードされると (プログラムがそのスコープを離れたときに発生します)、そのフレームが保持していたすべての参照が解放されます。これは、ヒープ上の 1 つ以上のオブジェクトが、スタック上の何かによって直接的または間接的に参照されなくなったことを意味する場合があります。これらは、ガベージ コレクションに使用できるオブジェクトです。オブジェクトがガベージ コレクションされるかどうかを知りたい場合は、そのオブジェクトが現在スタックに接続されているかどうかを確認するだけです。

このようなオブジェクトは、自動的にガベージ コレクションされるのではなく、ガベージ コレクションで使用できることに注意してください。そのようにマークされたオブジェクトは、コレクターが選択した時点で取り壊されます。おそらく決してありません。finalize()は、収集されるすべてのオブジェクトに対して実行されます。これにより、収集時に特定のことが確実に発生するようになりますが、確実に発生することを保証できない場合、有用性は限定されます。

次に、例を示します。

public void A() {//entering this method creates a new stack frame
  MyObject obj = new MyObject();//'obj' is a reference belonging to the current stack frame.
    //the obj reference is now pointing to a place in memory on the heap

  this.B();
}

public void B() { //Now we are in a new stack frame on top of the older one.
  obj.doSomething();//Doesn't work! There is no 'obj' reference in this stack frame
    //This results in a null pointer exception
  MyObject obj2 = new MyObject();//A totally new object is created on the heap!
} //When we leave this method we leave the scope, and the stack frame. 
 //obj2 is no longer referenced, and so is available for garbage collection

最後に 1 つ。3 つのオブジェクトをインスタンス化するとします。AB、およびC。これらのオブジェクトのメンバー変数としてC渡されA、保存されます。ここで、が定義されBているスコープを離れるとしましょう。まだそれへの参照があるため、ガベージコレクションされません。に保持されているものを保持しているスタック上の場所がまだあります。BCAC

于 2013-09-13T19:04:20.007 に答える