Вопрос

Этот вопрос касается, в частности, языка 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();
    }
}
Это было полезно?

Решение

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

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

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

Объект, на который ссылается статическая переменная-член, является строгой ссылкой до тех пор, пока класс не будет выгружен.Нормальный 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's a constant. */
  }
}

Другие советы

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top