web-dev-qa-db-fra.com

Heap vs Stack vs Perm Space

  • Quelles sont les différences entre les espaces mémoire Java (Espace Perm, Pile Espace, Espace Tas))?
  • Quand la JVM utilise-t-elle l'un ou l'autre?
  • Si j'utilise Scala/Groovy/etc., Y a-t-il des différences?
37
caarlos0

Simplement

  • Espace de tas: tous les objets vivants sont alloués ici.
  • Espace de pile: stocke les références à l'objet pour la variable dans l'appel de méthode ou l'instanciation de variable.
  • Espace permanent: stocke les informations sur les classes chargées

Par exemple:

Student std = new Student();

après avoir exécuté la ligne au-dessus de l'état de la mémoire sera comme ceci.

  • Tas: stocke "new Student ()"
  • Pile: stocke des informations sur "std"
  • Perm Space: stocke des informations sur la classe Student
83
Kowser

Pardonnez-moi d'avoir ajouté une réponse à une question aussi ancienne - La réponse actuelle est excellente, mais il manque quelques cas Edge à cause du code statique et des mises à jour Java 8).

Présentation

  • Empiler
    • Alloué par thread
    • Stocke les références locales et les primitives
    • Ceci est une mémoire limitée - Lorsqu'une méthode ou un thread se termine, toutes leurs données dans la pile sont perdues
    • A l'accès le plus rapide, donc une primitive locale est plus rapide à utiliser qu'un objet local
  • Tas
    • Toutes les instances d'objet allouées existent ici
    • Divisé en générations, la plus jeune génération étant le premier endroit où GC regarde
    • Disponible pour tous les threads donc les allocations et les désallocations doivent être synchronisées
    • Cette mémoire peut devenir fragmentée ( mais vous ne gérez généralement pas cela vous-même)
  • PermGen
    • Stocke les informations sur les classes chargées
    • Stocke des informations immuables (primitives, chaînes internées)
    • Stocke la classe statique membres

Exemple de code

public class SimpleVal { //The Class (loaded by a classloader) is in the PermGen

    private static final int MAGIC_CONSTANT = 42; //Static fields are stored in PermGen
    private static final SimpleVal INSTANCE = new SimpleVal(1); //Static field objects are created in the heap normally, with the reference in the PermGen ('class statics' moved to the heap from Java 7+)
    private static SimpleVal previousInstance; //Mutable static fields also have their reference in PermGen so they can easily cause memory leaks

    private int value; //Member variables will be part of the heap

    public SimpleVal(int realValue) {
        value = realValue;
        ...
    }

    public static int subtract(SimpleVal val1, SimpleVal val2) {
         ....
    }

    public int add(SimpleVal other) { //Only one copy of any method (static or not) exists - in PermGen
         int sum = value + other.value; //Local values in methods are placed in the Stack memory
         return sum;
    }

}

public static void main(String[] args) {

    SimpleVal val1 = null;
    SimpleVal val2 = new SimpleVal(3); //Both of these variables (references) are stored in the Stack 

    val1 = new SimpleVal(14); //The actual objects we create and add to the variables are placed in the Heap (app global memory, initially in the Young Gen space and later moved to old generation, unless they are very large they can immediately go old gen)

    int prim = val1.add(val2); //primitive value is stored directly in the Stack memory
    Integer boxed = new Integer(prim); //but the boxed object will be in the heap (with a reference (variable) in the Stack)

    String message = "The output is: "; //In Java 7+ the string is created in the heap, in 6 and below it is created in the PermGen
    System.out.println(message + prim);

}

Java 8 Remarque: L'espace PermGen a été remplacé par ce qu'on appelle Metaspace. Cela fonctionne toujours de la même manière mais peut être redimensionné automatiquement - par défaut, Metaspace augmente automatiquement sa taille dans la mémoire native jusqu'à un maximum (spécifié dans les paramètres JVM), mais PermGen a toujours une taille maximale fixe contiguë à la mémoire de tas.

Android Note: De Android 4.0 (à partir de 3.0 en pratique) Android devrait respecter les contrats de mémoire décrits - mais sur les anciennes versions, la l'implémentation a été cassée . La mémoire 'Stack' dans Android-Davlik est en fait basée sur les registres (les tailles et les nombres d'instructions varient entre les deux, mais pour un développeur la fonctionnalité reste la même).

Enfin, pour plus d'informations, la meilleure réponse que j'ai jamais vue à ce sujet sur StackOverflow est ici

9
Nick Cardoso