web-dev-qa-db-ja.com

静的フィールドはガベージコレクション用に開いていますか?

プログラムのセットアップでのみ使用される架空のユーティリティクラスがある場合:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

myObjectは、使用されなくなったときにガベージコレクションされますか、それともプログラムの存続期間中は保持されますか?

84

クラスがロードされている間、静的変数をガベージコレクション用に選択することはできません。これらは、それぞれのクラスローダー(このクラスのロードを担当した)自体がガベージのために収集されるときに収集できます。

JLSセクション12.7クラスとインターフェイスのアンロード を確認してください

クラスまたはインターフェースは、その定義クラスローダーがガベージコレクターによって再利用できる場合にのみアンロードできます[...] bootstrapローダーによってロードされたクラスおよびインターフェースはアンロードできません。

105
bruno conde

静的変数は、ClassLoaderが参照するClassオブジェクトによって参照されます。したがって、ClassLoaderが何らかの方法でClassをドロップする場合(可能な場合)、またはClassLoader自体が静的変数を収集する(可能性が高い-Webアプリのアンロードを考える)むしろ、それらが参照するオブジェクト)は収集されません。

47
Jon Skeet

一時的なオブジェクトを静的初期化に使用してから破棄する場合は、静的初期化ブロックを使用できます。

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

静的初期化ブロックは特別な種類の静的メソッドであるため、myObjectはローカル変数であり、ブロックの実行終了後にガベージコレクションできます。

13
finnw

myObjectはreferenceであり、objectではありません。オブジェクトは、参照できないために到達できないため、オブジェクトが自動的にガベージコレクションされます。

そのため、静的参照「myObject」の背後にあるオブジェクトも、参照解除するとガベージコレクションされる可能性があります。

myObject = null;

このオブジェクトへの他の参照はありません。

ただし、プログラムの存続期間中は静的な参照と変数が残ります。

9
Felix Keil

this があなたの質問に答えると思います-基本的に、クラスが特別なクラスローダーから来て、それがクラスをアンロードしない限りではありません。

7
Tom

ここで重要なのは、クラスインスタンスのガベージコレクション、つまりオブジェクトです。 ClassLoaderインスタンスは、本質的にオブジェクトです。そのため、Classloaderオブジェクトがガベージコレクションされていない場合、ヒープ(つまり静的なもの)に格納されているそれらの参照はほとんどガベージコレクションされません。例外は文字列プールです。

したがって、あなたが突然private static MyGiantClass myGiantObject = new MyGiantClass()を実行することを決定する前に、私が難しい方法を学んだので、よく考えてください。

0
ha9u63ar