Подтвердить что ты не робот

Что со статической памятью в java?

Этот вопрос касается, в частности, языка java. Я понимаю, что для статического кода есть статический протектор памяти.

Мой вопрос: как заполняется эта статическая память? Статический объект помещается в статическую память при импорте или при первой ссылке? Кроме того, применяются ли те же правила сбора мусора для статических объектов, как и для всех других объектов?


public class Example{
    public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;

public class MainApp{
    public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
       Example.someO.someMethod();
// Do the same garbage collection rules apply to a 
//     static object as they do all others?
       Example.someO = null;
       System.gc();
    }
}
4b9b3361

Ответ 1

Импорт не коррелирует с любыми инструкциями в скомпилированном коде. Они устанавливают псевдонимы для использования только во время компиляции.

Существуют некоторые отражающие методы, которые позволяют загружать класс, но еще не инициализированы, но в большинстве случаев вы можете предположить, что всякий раз, когда ссылается на класс, он был инициализирован.

Инициализаторы статического члена и статические блоки выполняются так, как если бы они были одним статическим блоком инициализатора в порядке исходного кода.

Объект, на который ссылается статическая переменная-член, строго ссылается, пока класс не будет выгружен. Обычный ClassLoader никогда не выгружает класс, но те, которые используются серверами приложений, выполняются в правильных условиях. Тем не менее, это сложная область и является источником многих трудно диагностируемых утечек памяти, но еще одна причина не использовать глобальные переменные.


Как (тангенциальный) бонус, здесь сложный вопрос:

public class Foo {
  private static Foo instance = new Foo();
  private static final int DELTA = 6;
  private static int BASE = 7;
  private int x;
  private Foo() {
    x = BASE + DELTA;
  }
  public static void main(String... argv) {
    System.out.println(Foo.instance.x);
  }
}

Что будет печатать этот код? Попробуйте, и вы увидите, что он печатает "6". Здесь есть несколько вещей, и один из них - порядок статической инициализации. Код выполняется так, как если бы он был написан следующим образом:

public class Foo {
  private static Foo instance;
  private static final int DELTA = 6;
  private static int BASE;
  static {
    instance = null;
    BASE = 0;
    instance = new Foo(); /* BASE is 0 when instance.x is computed. */
    BASE = 7;
  }
  private int x;
  private Foo() {
    x = BASE + 6; /* "6" is inlined, because it a constant. */
  }
}

Ответ 2

Обычно нет такой вещи, как "статическая" память. Большинство vm имеют постоянное поколение кучи (где классы загружаются), что обычно не собирают мусор.

Статические объекты выделяются точно так же, как и любой другой объект. Но, если они живут долго, они будут перемещены между разными поколениями в сборщике мусора. Но они не попадут в область permgenspace.

Если ваш класс постоянно держится за этот объект, он будет освобожден только после выхода vm.

Ответ 3

Эта статическая переменная some0 инициализируется, как только ваш класс ссылается на ваш код. В вашем примере это будет выполнено в первой строке вашего основного метода.

Вы можете проверить это, создав блок статического инициализатора. Поместите точку останова в этот блок инициализатора, и вы увидите, когда он будет вызван. Или еще проще... поставьте точку останова в конструкторе SomeObject.

Ответ 4

Инициализация статических переменных описана в разделе 2.11 Статические инициализаторы солнц JVM spec. Спецификация не определяет реализацию коллекции Garbage, однако я предполагаю, что правила сбора мусора для статических объектов будут различаться в зависимости от вашей виртуальной машины.

Ответ 5

Следует отметить, что только указатель (или любой другой примитивный тип) сохраняется в PermGenSpace (это собственное имя для область, где хранится статический материал).

Таким образом, объект, на который ссылается указатель, находится в обычной куче, как и любой другой объект.

Ответ 6

Если статическое поле изменено для ссылки на другой объект, исходный объект, на который указывает статическое поле, имеет право на GC, как и любой другой объект.

Он также может быть свободен (даже если не нулевым), если сам класс выгружается, а весь граф объекта вырезается из кучи. Конечно, когда класс может быть выгружен, это хорошая тема для множества других вопросов...:)