Что со статической памятью в 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();
}
}
Ответы
Ответ 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, как и любой другой объект.
Он также может быть свободен (даже если не нулевым), если сам класс выгружается, а весь граф объекта вырезается из кучи. Конечно, когда класс может быть выгружен, это хорошая тема для множества других вопросов...:)