Java Stack vs Heap : Guide Pratique d'Allocation Mémoire
Qu'est-ce que la Mémoire Stack ?
En Java, la pile (stack) est une région de mémoire contigüe qui contient les cadres d'appel de méthodes, les variables locales et les variables de référence. Chaque fois qu'une méthode est invoquée, un nouveau cadre est empilé sur la pile. La mémoire stack est organisée selon le principe Last-In, First-Out (LIFO), ce qui signifie que l'appel le plus récent est le premier à être retiré lorsque la méthode se termine.
Qu'est-ce que la Mémoire Heap ?
Le tas (heap) est la zone où les objets Java sont créés. Il contient toutes les instances de classes et, éventuellement, les variables de référence qui pointent vers ces objets. Contrairement à la pile, le tas n'est pas lié à la durée de vie d'un seul appel de méthode, permettant aux objets de persister au-delà de la portée dans laquelle ils ont été créés.
Allocation Mémoire en Java
L'allocation mémoire en Java désigne le processus de réservation de mémoire virtuelle pour les données du programme. Les variables ne sont pas allouées à la déclaration ; au lieu de cela, une référence est créée. Lorsque l'opérateur new est utilisé, la JVM alloue de l'espace sur le tas pour l'objet.
Java divise la mémoire en quatre sections distinctes pour une gestion efficace :
- Heap (Tas)
- Stack (Pile)
- Code (Bytecode)
- Static (Données de classe)
- La section Code contient le bytecode compilé.
- La Stack contient les cadres de méthodes, les variables locales et les variables de référence.
- Le Heap stocke les objets et, occasionnellement, des variables de référence.
- La section Static conserve les champs et méthodes statiques.
Variables Locales vs Variables d'Instance
Les variables d'instance sont déclarées dans une classe mais en dehors de toute méthode :
class Etudiant {
int num; // variable d'instance
public void showData() {}
}
Les variables locales sont déclarées à l'intérieur d'une méthode (ou comme paramètres de méthode) :
public void sum(int a) {
int x = a + 3; // a et x sont des variables locales
}
Stack vs Heap en Action
Examinons un exemple pour illustrer l'interaction entre la pile et le tas lors d'appels de méthodes.
Supposons que la méthode main appelle m1() :
public void m1() {
int x = 20;
}
Un cadre pour m1 est empilé sur la pile. La variable locale x est stockée dans ce cadre.
Lorsque m1 appelle m2(int b), un nouveau cadre est ajouté au-dessus de celui de m1 :
public void m2(int b) {
boolean c;
}
De même, m2 appelle m3(), créant un autre cadre :
À l'intérieur de m3, un objet Compte est instancié sur le tas, tandis que sa référence ref vit sur la pile :
class Compte {
int p;
int q;
}
public void m3() {
Compte ref = new Compte(); // code additionnel
}
La variable de référence ref est créée dans le cadre de pile de m3 et pointe vers l'objet Compte alloué sur le tas.
Lorsque m3 se termine, son cadre de pile est dépilé, laissant l'objet Compte sans aucune référence. Il devient éligible au garbage collection.
Le même processus se répète pour m2 et m1, rendant finalement le contrôle à main.
Références d'Objets comme Variables d'Instance
Considérez une classe A qui contient une référence vers une instance de B :
public static void main(String[] args) {
A parent = new A(); // code additionnel
}
class A {
B child = new B();
int e;
}
class B {
int c;
int d;
}
Ici, la référence child est stockée sur le tas en tant que partie de l'objet A, pointant vers sa propre instance B.
Points Clés à Retenir
- Chaque appel de méthode crée un nouveau cadre sur la pile.
- Les variables locales résident sur la pile ; les variables d'instance sont sur le tas.
- Les variables de référence sont stockées sur la pile mais pointent vers des objets du tas.
- Lorsqu'un cadre de pile est dépilé, ses variables locales et de référence sont supprimées, et tout objet orphelin du tas devient éligible au garbage collection.
Java
- Variables et littéraux en Java : Guide complet
- Classes et objets en Java : Guide pratique
- Classes et méthodes abstraites en Java : guide complet
- Maîtriser les classes imbriquées et internes en Java : types, exemples et bonnes pratiques
- Java throw vs throws : maîtriser la gestion d'exceptions avec exemples pratiques
- Types d'annotations Java : guide complet des annotations prédéfinies, personnalisées et méta
- Maîtriser l'autoboxing et l'unboxing Java : Exemples pratiques et bonnes pratiques
- Maîtriser le remplacement de chaînes Java : replace(), replaceAll() et replaceFirst() expliqués
- Redéfinition de méthodes Java : Personnaliser le comportement de la superclasse