2009-05-12 4 views
95

私はいくつかの古い本を閲覧していて、Peter Haggerの "Practical Java"のコピーを見つけました。パフォーマンスセクションでは、不要になったオブジェクト参照をnullに設定することを推奨します。Javaオブジェクトをnullに設定することはもう何も行いませんか?

Javaでは、オブジェクト参照をnullに設定すると、パフォーマンスやガベージコレクションの効率が向上しますか?もしそうなら、どのような場合にこれが問題なのでしょうか?コンテナクラス?オブジェクトの構成?匿名の内部クラス?

私はこれをコードでよく見ます。これは現在、時代遅れのプログラミングアドバイスですか、それともまだ有用ですか?

+2

それをプロファイルします。現代のランタイムでは、パフォーマンスやメモリ占有量の意味のある増加は見られません。 –

+12

@Jason、プロフィール?これは、十分な結果セットを得るために十分な大きさのケースをプロファイルして、これに答えることを前提としています。そして、私はVMがgcとパフォーマンスの問題を隠すのに十分最適化されているケースを選びません。だから私はここでこれを求めている。これが問題である場合の感覚を得る。 – sal

+1

http://stackoverflow.com/questions/449409/does-assigning-objects-to-null-in-java-impact-garbage-collectionの重複。 –

答えて

65

参照を無効にすることを考えていたときには、これは少し異なります。

A-> B-> Cというオブジェクトチェーンがある場合、Aには到達できない場合、A、B、Cはすべてガベージコレクションの対象となります(他のものはBまたはCを指していると仮定します)。明示的に参照A-> BまたはB-> Cをヌルに設定する必要はなく、決して必要はありません。

それ以外にも、実際にはコレクションのオブジェクトを扱っているため、ほとんどの場合、問題は実際には発生しません。一般的には、適切なremove()メソッドを呼び出すことによって、リストやマップなどからオブジェクトを削除することを常に考えなければなりません。

ヌルへの参照を設定するいくつかのアドバイスであることを用いる場合には、メモリ集約オブジェクトスコープ途中で使用されるように停止長い範囲に具体的でした。例えば:ここ

{ 
    BigObject obj = ... 
    doSomethingWith(obj); 
    obj = null;    <-- explicitly set to null 
    doSomethingElse(); 
} 

根拠はOBJがスコープ内に残っているので、その後の参照を明示的にヌル化せず、それはdoSomethingElse()メソッドが完了するまでごみ収集可能になっていないということでした。そしてこれは、が現代のJVMのにはおそらく存在しないとのアドバイスです.JITコンパイラは、特定のローカルオブジェクト参照が使用されなくなった時点でうまくいくことが分かります。

+1

ローカル変数はマシンによって最適化できます。クラス変数はできません。私はワーカースレッドが(スレッドプール上の)ワーカースレッドが要求を処理した後、それらのオブジェクトを解放しないように、ワーカースレッドに新しいタスク(新しい状態のオブジェクトを直ちに上書きする)大きな状態のオブジェクトと何百ものワーカースレッド(ビッグhttpサーバ)を使用すると、これは保持されたままの大量のメモリであり、まだ使用されません。 –

+0

私はおそらくちょうど追加する必要があります:上記のアドバイスは、よく振る舞うライブラリ、よく振る舞うVMなどを前提としたアドバイスです。オブジェクトにハングするスレッドプールライブラリ仕事が終わった後、うーん...それはおそらくオブジェクト参照をnullにすることによって回避することができますが、バグの少ないスレッドプールライブラリを使用して回避することもできるスレッドプールライブラリのバグです。このようなバグが一般的な設計原則を変更するかどうかはわかりません。 –

24

いいえ、それは時代遅れのアドバイスではありません。ダブリング参照は、特に、事前割り当て配列を使用して拡張可能な配列コンテナ(ArrayListなど)を実装する場合は、依然として問題です。リストの「論理的」サイズを超える要素は、ゼロにする必要があります。そうでないと、解放されません。

有効なJava第2版、項目6:廃止されたオブジェクト参照を削除するを参照してください。

+0

これは言語の問題かVMの実装の問題ですか? –

+4

これは「意味」の問題です。基本的には、配列を事前に割り当てているため、VMはそれを認識します。コンテナの「論理的な」サイズについては何も知らない。 16要素配列に裏打ちされたサイズ10のArrayListがあるとします。 VMはアイテム10..15が実際に使用されていないことを知ることはできません。それらのスロットに内容がある場合、解放されません。 –

+0

コンテナクラスの外はどうですか?内側のオブジェクトが外側のオブジェクトによって割り当て解除されないオブジェクトの構成では、 – sal

4

メモリ制限環境(携帯電話など)では、これが便利です。 nullを設定することにより、オブジェクトはスコープから出て変数を待つ必要はありません。

しかし、毎日のプログラミングでは、Chris Jester-Youngが引用したような特殊なケースを除いて、これはルールではありません。

9

インスタンスフィールド、配列要素

オブジェクトへの参照がある場合、それはごみを収集することができません。特にそのオブジェクト(およびその背後にあるグラフ全体)が大きければ、ガベージコレクションを停止する参照は1つしかなく、その参照は実際にはもう必要ではなく、それは残念な状況です。

病理学的事例は、それを構成するために使用されたXML DOMツリー全体の不規則なインスタンス、登録されていないMBean、または全体を妨げる展開されていないWebアプリケーションのオブジェクトへの単一の参照クラスローダーがアンロードされるのを防ぎます。

したがって、参照自体を保持しているオブジェクトが、とにかく(またはそれ以降でも)ガベージコレクションされることが確実でない場合は、不要になったものはすべて無効にする必要があります。それがガベージコレクタによって再利用することができ、今から使えなく」としてそれをマークするようにしますが、その範囲の終了前にnullにローカル変数を設定することを検討している場合

:変数をスコープ

より限定された範囲に入れることを検討すべきです。

{ 
    BigObject obj = ... 
    doSomethingWith(obj); 
    obj = null;   // <-- explicitly set to null 
    doSomethingElse(); 
} 

{ 
    { 
    BigObject obj = ... 
    doSomethingWith(obj); 
    } //   <-- obj goes out of scope 
    doSomethingElse(); 
} 

長くなり、フラットスコープは、あまりにも、コードの読みやすさのために、一般的に悪いです。その目的のためだけに物事を壊すためのプライベートな方法を導入することもあまり知られていません。

+0

強参照を参照している場合は、これは当てはまりますが、すべての参照には当てはまりません。 Javaの弱い参照はガベージコレクションされる可能性があります。 –

0

まず、オブジェクトをnullに設定していることを意味するものではありません。実際に、我々はメモリに保存されているのArrayListオブジェクトのオブジェクト参照変数名のリスト1を作成している、我々がやっていること上記のコードセグメントで

List list1=new ArrayList(); 
List list2=list1; 

:私は下にそれを説明します。したがって、list1はそのオブジェクトを参照しており、それは変数以上のことを指摘しています。 そして、2行目のコードでlist1のリファレンスをlist2にコピーしています。私がしなければ は、だから今、戻ってあなたの質問に行く:

list1=null; 

リスト2も参照してくださいすることは何も持っていないだろうので、リスト1は、もはやメモリに保存されている任意のオブジェクトを参照している意味しています。あなたはLIST2のサイズチェックすると だから:ガベージコレクタの概念はオブジェクトによって保持されたメモリを解放することを心配する「あなたは何も言わないどの到着するので、ここで

list2.size(); //it gives you 0 

をするとき、私は、私はそれを行いますそれがもはやプログラムで使われなくなり、JVMが私を管理することに気づくでしょう。

私はそれがコンセプトをクリアすることを願っています。

0

これを行う理由の1つは、廃止されたオブジェクト参照を排除することです。 あなたはテキストを読むことができますhere.

関連する問題