2013-05-16 13 views
12

私はいくつかのJavaガベージコレクションガイドをオンラインで読んだことがありますが、私はまだ不明な点があり、コードにメモリリークがないようにしたいと思っています。インスタンス変数にまだ参照がある場合、Java GCはオブジェクトを破棄しますか?

Java GCは参照を失ったオブジェクトを収集しますが、その変数にはまだ参照がありますか?

それでは、私はSomeObjectのを持っているとしましょう:

public class SomeObject { 
    public ObjectVar var; 

    public SomeObject() { 
     var = new ObjectVar(); 
    } 
} 

そして、私のコード:

SomeObject obj1 = new SomeObject(); 
SomeObject obj2 = new SomeObject(); 
obj2.var = obj1.var; 
obj1 = null; 

だから、OBJ1のVaRは、参照を持っていませんが、OBJ1は、もはや任意の参照を持っています。では、GCはobj1を破壊しますが、varは生きていますか? (私はそう仮定している;確かにしたい)。ありがとう!

+0

GCの基本ルールは、オブジェクトのGC処理がプログラムに影響する場合、それは起こらないということです。 (GCを気にする特別なツールを使用しているのでなければ、それを使用している場合は分かります) –

+0

["Midlife Crisis"](http://blogs.msdn。 com/b/ricom/archive/2003/12/04/41281.aspx)。 – Mehrdad

答えて

12

が起こるために何が起こっているかであるobj2からの参照を持っている、特に以来、(に触れてはいけません)そのままですobj2obj2.varとして参照されobj1.var元 - 以下のコメント)最後に

// obj1 and obj1.var get created 
SomeObject obj1 = new SomeObject(); 
// obj2 and obj2.var get created 
SomeObject obj2 = new SomeObject(); 
// old obj2.var becomes eligible for GC 
obj2.var = obj1.var; 
// obj1 becomes eligible for GC 
obj1 = null; 

、2つのオブジェクトがGCDを得ることはありませんことを残ります。

SomeObjectの非静的内部クラスであるObjectVarクラスの特別な場合に、obj1.varへの参照を維持することも周りobj1を維持するであろう。これは内部的にはSomeObject.ObjectVarクラスに内部クラスの外部オブジェクトを参照するタイプSomeObjectの隠し変数があるためです。

+0

ありがとう!しかし、今私は2人が異なる答えを持っているので混乱しています。 ObjectVarがSomeObjectのサブクラス(または内部クラス)だった場合、上記のコードはobj1がGCに対して不適格になるでしょうか? – baekacaek

+1

@bekacaek ZyyaoWeiのコメントは静的内部クラスとみなされていますが、その場合は実際には関係ありません。非静的な内部クラスと匿名または名前付きのメソッドローカルクラスは、ホストオブジェクトのガベージコレクションを維持することができますが、静的な内部クラスではできません。 – dasblinkenlight

+0

もう一度説明していただきありがとうございます。 – baekacaek

3

もちろんです。

varフィールドに格納する内容は、オブジェクト自体ではなく、オブジェクトを参照することに注意してください。 GCはobj1を収集するときので、varオブジェクトは、それが(参照、まだ健在です。..ここ

+0

ObjectVarがSomeObjectの内部クラスである場合も同じことが適用されますか? – baekacaek

+0

これは問題ではありません。なぜなら、obj2がそのオブジェクトへの参照を持っているからです。 –

+2

静的な内部クラスの場合は、実際には問題ありません。しかし、静的ではない内部クラスの場合、 'var'は外部クラスへの「後方参照」を持ちます。これにより、所有者は予想以上に長く生き続けることがあります。 – dasblinkenlight

0

はい - 動作はあなたの説明通りです。ガベージコレクションの一般的なルールは、オブジェクトがハードリファレンスを通じてそれらに到達できない場合にのみ適格になることです。したがって、この方法で到達できるオブジェクトはガベージコレクションされません(ソフト/弱参照は例外です)。

0

単純に言えば、参照のパスによってオブジェクトがまだ到達可能な場合、コレクションの存続が保証されます。そのようなパスがない場合、オブジェクトにアクセスできなくなり、安全に収集することができます。

は、最初の二行の後、メモリは次のようになります。ガベージコレクションがこの時点で発生した場合

o1 --> SomeObj#1 --> ObjectVar#1 
o2 --> SomeObj#2 --> ObjectVar#2 

全4オブジェクトは、到達することができ、それらのどれもが収集されないであろう。 3行目の後

は、それは次のようになります。今

o1 --> SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

、唯一の3つのオブジェクトに到達することができます。ガベージコレクタはObjectVar#2を削除することがあります。第四行の後

、それは次のようになります。

o1  SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

のみ2つのオブジェクトがまだ到達可能です。ガベージコレクタはSomeObj#1とObjectVar#2を削除することができますが、SomeObj#2とObjectVar#1は保持する必要があります。

関連する問題