Question

Cette question concerne le langage Java en particulier. Je comprends qu’une partie statique de la mémoire est réservée à tout code statique.

Ma question est la suivante: comment cette mémoire statique est-elle remplie? Un objet statique est-il mis en mémoire statique à l'importation ou à la première référence? De même, les mêmes règles de récupération de place s'appliquent-elles aux objets statiques comme à tous les autres objets?


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();
    }
}
Était-ce utile?

La solution

Les importations ne sont en corrélation avec aucune instruction du code compilé. Ils établissent des alias à utiliser uniquement au moment de la compilation.

Certaines méthodes de réflexion permettent à la classe d'être chargée mais pas encore initialisée, mais dans la plupart des cas, vous pouvez supposer que chaque fois qu'une classe est référencée, elle est initialisée.

Les initialiseurs de membres statiques et les blocs statiques sont exécutés comme s'il s'agissait d'un seul bloc d'initialisation statique dans l'ordre du code source.

Un objet référencé par une variable membre statique est fortement référencé jusqu'à ce que la classe soit déchargée. Un ClassLoader normal ne décharge jamais une classe, contrairement à ceux utilisés par les serveurs d'applications dans les bonnes conditions. Toutefois, c’est un domaine délicat qui a été à l’origine de nombreuses fuites de mémoire difficiles à diagnostiquer et qui constituent une autre raison de ne pas utiliser de variables globales.

En tant que bonus (tangentiel), voici une question délicate à prendre en compte:

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'est-ce que ce code imprimera? Essayez-le et vous verrez qu'il affiche "6". Quelques éléments sont à l’œuvre ici, l’un étant l’ordre d’initialisation statique. Le code est exécuté comme s'il était écrit comme suit:

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

Autres conseils

Normalement, il n’existe pas de " statique " Mémoire. La plupart des vm ont la génération permanente du tas (où les classes sont chargées), ce qui n'est normalement pas un ramasse-miettes.

Les objets statiques sont alloués comme n'importe quel autre objet. Mais s'ils vivent longtemps, ils seront déplacés entre les différentes générations dans le ramasse-miettes. Mais ils ne finiront pas dans un espace permanent.

Si votre classe conserve cet objet de façon permanente, il ne sera libéré que lorsque la machine virtuelle est fermée.

Cette variable statique some0 est initialisée dès que votre classe est référencée dans votre code. Dans votre exemple, cela sera exécuté en première ligne de votre méthode principale.

Vous pouvez le valider en créant un bloc d’initialisation statique. Placez un point d'arrêt dans ce bloc d'initialisation et vous verrez quand il sera appelé. Ou encore plus simple ... mettez un point d'arrêt dans le constructeur de SomeObject.

L'initialisation des variables statiques est traitée dans la section 2.11 Initialisateurs statiques des spécifications de la machine virtuelle Java de soleils. La spécification ne définit pas l'implémentation de la récupération de place, donc j'imagine que les règles de récupération de place pour les objets statiques varieront en fonction de votre machine virtuelle.

Il convient de noter que seul le pointeur (ou tout autre type de primitive) est stocké dans PermGenSpace (c'est le nom correct pour la zone où le contenu statique est stocké).

Ainsi, l’objet référencé par le pointeur se trouve dans le tas normal, comme tout autre objet.

Si le champ statique est modifié pour faire référence à un objet différent, l'objet d'origine désigné par le champ statique est éligible pour le GC, comme tout autre objet.

Il pourrait également être libéré (même s'il n'est pas annulé) si la classe elle-même est déchargée et si le graphe d'objet entier est coupé du tas. Bien sûr, quand un cours peut être déchargé, c’est un bon sujet pour une foule d’autres questions ...:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top