Pregunta

Esta pregunta es para el lenguaje java en particular. Entiendo que hay un dispositivo estático de memoria reservado para todo el código estático.

Mi pregunta es ¿cómo se llena esta memoria estática? ¿Se coloca un objeto estático en la memoria estática en la importación o en la primera referencia? Además, ¿se aplican las mismas reglas de recolección de basura a los objetos estáticos que a todos los demás objetos?


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();
    }
}
¿Fue útil?

Solución

Las importaciones no se correlacionan con ninguna instrucción en el código compilado. Establecen alias para su uso solo en tiempo de compilación.

Hay algunos métodos de reflexión que permiten que la clase se cargue pero aún no se haya inicializado, pero en la mayoría de los casos, puede suponer que cada vez que se hace referencia a una clase, se ha inicializado.

Los inicializadores de miembro estático y los bloques estáticos se ejecutan como si fueran todos un bloque de inicializador estático en el orden del código fuente.

Se hace referencia a un objeto al que se hace referencia a través de una variable miembro estática hasta que se descarga la clase. Un ClassLoader normal nunca descarga una clase, pero las utilizadas por los servidores de aplicaciones lo hacen bajo las condiciones adecuadas. Sin embargo, es un área difícil y ha sido la fuente de muchas fugas de memoria difíciles de diagnosticar & # 8212; otra razón más para no usar variables globales.


Como un bono (tangencial), aquí hay una pregunta difícil de considerar:

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);
  }
}

¿Qué se imprimirá este código? Pruébalo y verás que se imprime " 6 " ;. Hay algunas cosas en funcionamiento aquí, y una es el orden de inicialización estática. El código se ejecuta como si estuviera escrito así:

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. */
  }
}

Otros consejos

Normalmente no existe tal cosa como " static " memoria. La mayoría de las máquinas virtuales tienen la generación permanente del montón (donde se cargan las clases), que normalmente no se recolecta como basura.

Los objetos estáticos se asignan como cualquier otro objeto. Pero, si viven por mucho tiempo, se moverán entre las diferentes generaciones en el recolector de basura. Pero no terminarán en el espacio permanente.

Si su clase mantiene este objeto de forma permanente, solo se liberará cuando vm salga.

Esta variable estática some0 se inicializa tan pronto como se hace referencia a su clase en su código. En su ejemplo, esto se ejecutará en la primera línea de su método principal.

Puede validar esto creando un bloque de inicializador estático. Ponga un punto de ruptura en este bloque de inicialización y verá cuándo se llamará. O incluso más simple ... ponga un punto de interrupción en el constructor de SomeObject.

La inicialización de las variables estáticas se trata en la Sección 2.11 Inicializadores estáticos de las especificaciones JVM de los soles. Sin embargo, la especificación no define la implementación de la recolección de basura, así que imagino que las reglas de recolección de basura para objetos estáticos variarán dependiendo de su máquina virtual.

Cabe señalar que solo el puntero (o cualquier otro tipo primitivo) se almacena en PermGenSpace (ese es el nombre apropiado para el área donde se almacena el material estático).

Por lo tanto, el objeto al que hace referencia el puntero se encuentra en el montón normal, como cualquier otro objeto.

Si el campo estático se cambia para hacer referencia a un objeto diferente, el objeto original al que apunta el campo estático es elegible para GC como cualquier otro objeto.

También se podría liberar (incluso si no se anula) si la clase en sí está descargada y todo el gráfico de objetos se recorta del montón. Por supuesto, cuando una clase se puede descargar es un buen tema para muchas otras preguntas ... :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top