古い本をいくつか読んでいたところ、Peter Haggerによる「Practical Java」のコピーを見つけました。パフォーマンスのセクションでは、不要になったときにオブジェクト参照をnull
に設定することをお勧めします。
Javaでは、オブジェクト参照をnull
に設定すると、パフォーマンスまたはガベージコレクションの効率が向上しますか?ある場合、これはどのような場合に問題になりますか?コンテナクラス?オブジェクトの構成?匿名の内部クラス?
私はかなり頻繁にコードでこれを見ます。これは今では時代遅れのプログラミングのアドバイスですか、それともまだ有用ですか?
参照を無効にすることを考えていたときに少し依存します。
オブジェクトチェーンA-> B-> Cがある場合、Aに到達できない場合、A、B、およびCはすべてガベージコレクションの対象になります(他にBまたはCを参照していないと仮定)。たとえば、参照A-> BまたはB-> Cを明示的にnullに設定する必要はありません。
それとは別に、実際にはコレクション内のオブジェクトを扱っているため、ほとんどの場合、問題は実際には発生しません。通常は、適切なremove()メソッドを呼び出して、リストやマップなどからオブジェクトを削除することを常に考えてください。
以前使用されていた参照をnullに設定するためのアドバイスが特にあったのは-メモリ集中型オブジェクトがスコープの途中で使用されなくなった長いスコープでした。例えば:
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; <-- explicitly set to null
doSomethingElse();
}
ここでの理論的根拠は、objがまだスコープ内にあるため、参照の明示的なnullなしでは、doSomethingElse()メソッドが完了します。そして、これはおそらく現代のJVMにはもはや当てはまらない:というアドバイスです。JITコンパイラーは、特定のローカルオブジェクト参照が使用されなくなった時点で解決できることがわかります。
いいえ、時代遅れのアドバイスではありません。特に事前に割り当てられた配列を使用して拡張可能な配列コンテナー(ArrayList
など)を実装している場合は特に、ダングリング参照は依然として問題です。リストの「論理的な」サイズを超える要素はnullにする必要があります。そうしないと解放されません。
Effective Java 2nd ed、Item 6:Eliginate Obsolete Object References。
インスタンスフィールド、配列要素
オブジェクトへの参照がある場合、ガベージコレクションできません。特に、そのオブジェクト(およびその背後のグラフ全体)が大きい場合、ガベージコレクションを停止する参照が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();
}
一般に、長くてフラットなスコープは、コードの可読性にとっても悪いです。その目的のためだけに物事を分割するプライベートメソッドを導入することも前代未聞ではありません。
メモリが制限された環境(携帯電話など)では、これは便利です。 nullを設定することにより、objetcは変数がgcされるためにスコープから出るのを待つ必要がなくなります。
しかし、日常のプログラミングでは、クリスジェスターヤングが引用したような特別な場合を除いて、これはルールではありません。
まず、オブジェクトをnull
に設定しているという意味ではありません。以下に説明します。
List list1 = new ArrayList();
List list2 = list1;
上記のコードセグメントでは、メモリに格納されているArrayList
オブジェクトのlist1
のオブジェクト参照変数名を作成しています。したがって、list1
はそのオブジェクトを参照しており、変数にすぎません。コードの2行目では、list1
の参照をlist2
にコピーしています。だから今私がするならあなたの質問に戻って:
list1 = null;
つまり、list1
はメモリに保存されているオブジェクトを参照していないため、list2
も参照するものがありません。したがって、list2
のサイズを確認すると:
list2.size(); //it gives you 0
だからここにガベージコレクターの概念が到着します"オブジェクトによって保持されているメモリを解放することについて心配する必要はありません。 。"
コンセプトが明確になることを願っています。
これを行う理由の1つは、廃止されたオブジェクト参照を排除することです。テキストを読むことができます こちら