Javaで変数またはコレクションをnullに設定すると、ガベージコレクションとメモリ使用量の削減に役立ちますか?プログラムの実行時間が長く、各関数が繰り返し実行される可能性がある場合呼び出される(潜在的に数千回):親関数に値を返す前に、その中のすべての変数をnullに設定すると、ヒープサイズ/メモリの使用量を削減できますか?
それは古いパフォーマンスの伝承です。それは1.0日で真実でしたが、コンパイラーとJVMは(もしあれば)必要性を排除するために改善されました。興味があれば、この優れたIBMの記事で詳細を説明します。 Javaの理論と実践:ガベージコレクションとパフォーマンス
記事から:
明示的なnullの使用が役立つだけでなく、事実上必要な場合が1つあります。これは、オブジェクトへの参照のスコープが、プログラムの仕様で使用または有効と見なされるよりも広い範囲にある場合です。これには、ローカル変数ではなく、静的フィールドまたはインスタンスフィールドを使用して一時バッファーへの参照を格納する場合や、プログラムの暗黙のセマンティクスではなく、ランタイムからは到達可能である可能性がある参照を格納するために配列を使用する場合が含まれます。
翻訳:不要になった「明示的にnull」の永続オブジェクト。 (必要に応じて。「実質的に必要」という表現は強すぎますか?)
Java VM仕様
12.6.1ファイナライズの実装すべてのオブジェクトは、到達可能、ファイナライザ到達可能、到達不可能の2つの属性で特徴付けることができ、ファイナライズもファイナライズもファイナライズもできない場合があります。
到達可能なオブジェクトとは、任意のライブスレッドから継続する可能性のある計算でアクセスできる任意のオブジェクトです。プログラムの変換の最適化は、到達可能なオブジェクトの数を、本来は到達可能と見なされるオブジェクトの数よりも少なくするように設計できます。たとえば、コンパイラまたはコードジェネレータは、使用されなくなる変数またはパラメータをnullに設定して、そのようなオブジェクトのストレージをより早く再利用できる可能性があります。
討論
これの別の例は、オブジェクトのフィールドの値がレジスタに格納されている場合に発生します。その後、プログラムはオブジェクトではなくレジスタにアクセスし、オブジェクトに再びアクセスすることはありません。これは、オブジェクトがゴミであることを意味します。
継続する可能性のある計算に関与できるオブジェクトは到達可能です。したがって、コードがローカル変数を参照し、それ以外は何も参照しない場合、オブジェクトをnullに設定してオブジェクトを収集することができます。これにより、nullポインタ例外が発生するか、プログラムの動作が変更されるか、またはどちらでもない場合は、最初に変数が不要でした。
フィールドまたは配列要素をnullにする場合、一部のアプリケーションではそれが理にかなっている可能性があり、メモリの再利用が速くなります。大きな配列を作成して、クラスのフィールドが参照する既存の配列を置き換えると、置換が作成される前にフィールドがnullになると、メモリへの負担が軽減されます。
Javaのもう1つの興味深い機能は、スコープがクラスファイルに表示されないため、スコープは到達可能性に関連しないことです。これらの2つのメソッドは同じバイトコードを作成するため、VMは、作成されたオブジェクトのスコープをまったく表示しません。
static void withBlock () {
int x = 1;
{
Object a = new Object();
}
System.out.println(x+1);
}
static void withoutBlock () {
int x = 1;
Object a = new Object();
System.out.println(x+1);
}
必ずしも。オブジェクトへの参照を保持するライブスレッドがなくなると、オブジェクトはガベージコレクションの対象になります。
メソッドが戻ると、ローカル変数はスコープから外れ、ローカル変数をnullに設定してもまったく意味がありません-変数はいずれにしても消えます。変数が参照するオブジェクトへの参照を保持するものが他にない場合、それらのオブジェクトはガベージコレクションの対象。
重要なのは、変数だけでなく、それらの変数が参照するオブジェクトを見て、それらのオブジェクトがプログラムによって参照されている場所を見つけることです。
ローカル変数では役に立たないですが、不要になったインスタンス変数をクリアするのに役立ちます(初期化後など)。
(そうです、私はビルダーパターンを適用する方法を知っています...)
これはsomeがこのようないくつかのシナリオでのみ意味をなす可能性があります:
public void myHeavyMethod() {
List hugeList = loadHugeListOfStuff(); // lots of memory used
ResultX res = processHugeList(hugeList); // compute some result or summary
// hugeList = null; // we are done with hugeList
...
// do a lot of other things that takes a LOT of time (seconds?)
// and which do not require hugeList
...
}
ここではcouldhugeList = null
行だと思います。
しかし、メソッドを書き直すことは確かに意味があります(おそらく2つにリファクタリングするか、内部スコープを指定します)。
オブジェクト参照をnullに設定すると、ガベージコレクションの場合のみeligibleになります。ガベージコレクターが実行されるタイミングに依存する(JVMに依存)メモリを解放する必要はありません。ガベージコレクターが実行されると、ガベージコレクションの対象であるオブジェクトのみを削除してヒープを解放します。