web-dev-qa-db-ja.com

あまりにも多くの静的変数を使用すると、Javaでメモリリークが発生する可能性がありますか?

アプリケーションに静的変数またはメソッドが多すぎる場合、定義に従って、それらはヒープに格納されます。間違っている場合は修正してください

1)これらの変数は、アプリケーションが閉じられるまでヒープ上にありますか?
2)それらはいつでもGCに使用できますか?そうでない場合、それはメモリリークと言えるでしょうか。

46
harshit

静的メソッドは単なるメソッドであり、ヒープに格納されず、「this」パラメーターを使用できません。

静的変数は、GCの「ルート」として機能します。その結果、明示的にnullに設定しない限り、プログラムが存続する限り存続し、それらから到達可能なすべてのものも存続します。

メモリが解放されることを意図していて、解放されない場合にのみ、状況はメモリリークと見なされます。静的変数に一定期間オブジェクトへの参照を含める予定があり、そのオブジェクトを使い終わったときにそれをnullに設定し忘れた場合、リークが発生する可能性があります。ただし、それを静的変数に入れ、プログラムが実行されている限り存在することを意図している場合、それは間違いなくリークではなく、「永続的なシングルトン」である可能性が高くなります。まだ存在させたいオブジェクトが回収された場合、それは非常に悪かったでしょう。

ヒープに関する質問については、Java内のすべてのオブジェクトがヒープ上またはスタック上に存在します。オブジェクトはヒープ上にnew演算子で作成されます。その後、参照がそれらにアタッチされます。参照がnullになるか、範囲外(ブロックの終わりなど)になると、GCはそのオブジェクトに再び到達する方法がないことを認識し、それを再利用します。参照が静的変数にある場合、参照が外れることはありませんスコープですが、nullまたは別のオブジェクトに設定できます。

83
Uri

静的ハッシュマップがあり、それにデータを追加した場合...データが消えることはなく、リークが発生します-データが不要になった場合に備えて。データが必要な場合、それはリークではなく、大量のメモリがぶら下がっています。

3
ReneS

Staticによって直接または間接的に参照されるオブジェクトは、適切なクラスローダーが収集されるまでヒープに残ります。他のオブジェクトがクラスローダーを間接的に参照して、収集されないままになる場合があります(たとえば、ThreadLocal)。

たとえば静的なリストがあり、それに動的に参照を追加すると、非常に簡単に「オブジェクトの存続期間の競合の問題」が発生する可能性があります。多くの理由から、変更可能な静的変数を避けてください。

コードのどこかからこれらの変数を参照できる限り、GCedでそれを行うことはできません。つまり、アプリケーションの最後まで存在します。

それをメモリリークと呼んでもいいですか、私はメモリリークとは呼びません。通常、メモリリークとは、通常は回復するはずのメモリですが、回復することはありません。あるいは、その一部しか回復しません。また、メモリリークは通常、時間とともに悪化します(たとえば、メソッドを呼び出すたびに、より多くのメモリが「リーク」されます)。ただし、この場合、これらの変数のメモリ使用量は(種類が)静的です。

1
hhafez

それは古典的なCの意味でメモリリークを引き起こしません...例えば

Class A{

static B foo;

...

static void makeFoo(){
   foo = new B();
   foo = new B();
}

この場合、最初のインスタンスはガベージコレクションされる可能性があるため、makeFoo()を呼び出してもメモリリークは発生しません。

1
patros