Gestión de memoria en Java
⚡ Resumen inteligente
Gestión de memoria en Java explica cómo la JVM divide la memoria de tiempo de ejecución entre Stack, Heap, Codey las regiones estáticas, cómo fluyen las referencias a objetos durante las llamadas a métodos y cómo el recolector de basura recupera los objetos inaccesibles para que las aplicaciones se mantengan estables y libres de fugas de memoria.

¿Qué es la memoria de pila en? Java?
Memoria de pila en Java La pila es la región de memoria de la JVM que almacena los marcos de los métodos, las variables locales y las variables de referencia para cada hilo. Siempre se accede a la pila en orden de último en entrar, primero en salir, por lo que el método invocado más recientemente se encuentra en la parte superior, y sus variables locales se insertan y extraen junto con el marco.
Cada hilo en el Java La máquina virtual recibe su propia pila, que por diseño mantiene las invocaciones de métodos aisladas y seguras para subprocesos. Las variables locales primitivas, como int, boolean y double, residen directamente dentro del marco, mientras que las referencias a objetos almacenadas en la pila apuntan a objetos asignados en el montón.
¿Qué es la memoria de montón en Java?
La memoria del montón es la región compartida de la JVM que contiene cada Java Objeto y matriz creados con el operador new, junto con cualquier variable de referencia que pertenezca a esos objetos como campos de instancia. A diferencia de la pila, el montón se comparte entre todos los hilos, por lo que el acceso a los objetos a menudo requiere sincronización.
El montón (Heap) es el área que administra el recolector de basura. Las JVM HotSpot modernas dividen el montón en una generación joven para objetos de corta duración y una generación antigua para objetos de larga duración, con los metadatos de clase almacenados en una región nativa separada llamada Metaspace.
Asignación de memoria en Java
Asignación de memoria en Java Es el proceso mediante el cual la JVM reserva regiones de memoria virtual para variables e instancias de clases y estructuras durante la ejecución del programa. La memoria no se asigna a un objeto en el momento de su declaración; solo se crea una referencia. La asignación real del objeto se realiza mediante el operador `new`, por lo que cada objeto reside en el montón (Heap).
El Java La asignación de memoria se divide en las siguientes secciones:
- Montón
- Apilar
- Code
- Estático
Esta división de la memoria es necesaria para una gestión eficaz del tiempo de ejecución.
- El Code Esta sección contiene su compilado bytecode.
- El Apilar tiendas por secciones métodos, variables locales y variables de referencia.
- El Montón la sección contiene objetos y también puede contener variables de referencia almacenadas como campos de instancia.
- El Estático la sección contiene datos estáticos y métodos estáticos compartido en todas las instancias.
Diferencia entre variable local y de instancia
Comprender dónde reside cada tipo de variable en la JVM ayuda a explicar el comportamiento de la pila y el montón. Instancia variable se declara dentro de una clase pero fuera de cualquier métodoy vive en el Montón como parte de su objeto.
class Student{ int num; // num is instance variable public void showData{}
A variable local se declara dentro de un método, incluyendo los argumentos del métodoy reside en la pila dentro del marco activo.
public void sum(int a){ int x = a + 3; // a, x are local variables }
Diferencia entre pila y montón
La pila y el montón resuelven problemas diferentes dentro de la JVM. La pila proporciona a cada hilo una asignación rápida y determinista para datos de corta duración vinculados al ámbito de los métodos, mientras que el montón ofrece una región compartida para objetos de larga duración a la que cualquier hilo puede acceder. El breve vídeo a continuación resume las diferencias antes del tutorial que sigue.
Haga clic en aquí si el video no es accesible
Para ver cómo cooperan Stack y Heap, consideremos un método principal que llama al método m1.
public void m1{ int x = 20; }
En la pila de la JVM, se crea un marco para el método m1.
La variable x en m1 también se crea en el marco para m1 en la pila, como se muestra en la imagen a continuación.
El método m1 llama entonces al método m2. En la pila, se crea un nuevo marco para m2 encima del marco de m1.
Las variables locales b y c también se crean dentro del marco para m2 en la pila.
public void m2(int b){ boolean c; }
A continuación, m2 llama al método m3. Nuevamente, se crea un marco para m3 en la parte superior de la pila, como se muestra a continuación.
Ahora supongamos que el método m3 crea un objeto para la clase Account, que tiene dos variables de instancia int p y int q.
class Account { int p; int q; }
Aquí está el código para el método m3.
public void m3(){ Account ref = new Account(); // more code }
La instrucción new Account() crea un objeto de tipo Account en el Heap.
La variable de referencia ref se crea en la pila dentro del marco para m3.
El operador de asignación hace que la variable de referencia apunte al objeto en el Heap.
Una vez que el método finaliza su ejecución, el control regresa al método que lo llamó, que en este caso es el método m2.
El marco para el método m3 se vacía de la pila.
Dado que la variable de referencia ya no apunta al objeto en el Heap, ese objeto pasa a ser apto para la recolección de basura.
Una vez que el método m2 finaliza, se elimina de la pila y todas sus variables dejan de estar disponibles. Lo mismo ocurre con el método m1, y finalmente el control regresa al método principal.
¿Qué ocurre si un objeto contiene otra referencia como variable de instancia?
public static void main(String args[]) { A parent = new A(); // more code } class A { B child = new B(); int e; } class B { int c; int d; }
En este caso, la variable de referencia child reside en el Heap como parte del objeto A, y a su vez apunta a su propio objeto B, como se muestra a continuación.
¿Qué es la recolección de basura en Java?
Recolección de basura en Java Es el proceso mediante el cual la JVM gestiona la memoria automáticamente. El recolector de basura encuentra los objetos que ya no son accesibles desde ninguna referencia activa y recupera su memoria. La asignación dinámica de memoria se realiza mediante el operador `new`, y la memoria permanece asignada hasta que el programa deja de tener referencias al objeto.
Cuando no quedan referencias, el objeto se considera innecesario y la memoria que ocupa puede ser recuperada. No hay necesidad explícita de destruir un objeto porque Java Gestiona la desasignación automáticamente a través del recolector de basura.
La técnica que hay detrás de esto se conoce como Recolección de basuraLos programas que no liberan memoria terminan fallando cuando no queda nada que asignar. Se dice que tales programas tienen pérdidas de memoria. Recolección de basura en Java Se ejecuta automáticamente a lo largo de la vida útil del programa, lo que elimina la carga de la reasignación manual y reduce el riesgo de fugas.
En C, por el contrario, el programador es responsable de liberar la memoria asignada dinámicamente a través de la función free(). Aquí es donde Java La gestión de la memoria ofrece una gran ventaja.
Las JVM HotSpot modernas incluyen varios recolectores de basura optimizados para diferentes cargas de trabajo. El recolector de basura G1 predeterminado busca un rendimiento equilibrado y tiempos de pausa en montones de varios gigabytes. ZGC y Shenandoah buscan pausas de menos de un milisegundo en montones muy grandes, lo que los hace entractivo para servicios sensibles a la latencia. Elegir el recolector adecuado y ajustar los tamaños de Young Generation, Old Generation y Metaspace es una habilidad fundamental para Java trabajo escénico.
Nota: Todos los objetos se crean en la sección de memoria Heap, que es la región que gestiona el recolector de basura.
Ejemplo: aprender el mecanismo del recolector de basura en Java
Este tutorial muestra cuándo las referencias son aptas para ser eliminadas mediante la recolección de basura dentro de un programa sencillo.
Paso 1) Copie el siguiente código en un editor.
class Student{ int a; int b; public void setData(int c,int d){ a=c; b=d; } public void showData(){ System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); } public static void main(String args[]){ Student s1 = new Student(); Student s2 = new Student(); s1.setData(1,2); s2.setData(3,4); s1.showData(); s2.showData(); //Student s3; //s3=s2; //s3.showData(); //s2=null; //s3.showData(); //s3=null; //s3.showData(); } }
Paso 2) Guarda, compila y ejecuta el código. Como se muestra en el diagrama, se crean dos objetos y dos variables de referencia.
Paso 3) Descomenta las líneas 20, 21 y 22. Guarda, compila y ejecuta el código.
Paso 4) Como se muestra en el diagrama a continuación, dos variables de referencia ahora apuntan al mismo objeto.
Paso 5) Descomenta las líneas 23 y 24. Guarda, compila y ejecuta el código.
Paso 6) Como se muestra a continuación, s2 se vuelve nulo, pero s3 todavía apunta al objeto, por lo que el objeto aún no es apto para la recolección de basura.
Paso 7) Descomenta las líneas 25 y 26. Guarda, compila y ejecuta el código.
Paso 8) En este punto, ninguna referencia apunta al objeto, por lo que este se convierte en objeto de recolección de basura. El recolector de basura lo elimina de la memoria y no hay forma de recuperarlo.
Cómo eliminar un objeto en Java?
Java No proporciona un operador de eliminación manual, por lo que el enfoque estándar es eliminar todas las referencias al objeto para que el recolector de basura pueda recuperarlo.
1) Para que un objeto sea apto para la recolección de basura, asigne el valor nulo a todas las variables de referencia que apunten a él.
2) Los tipos primitivos no son objetos, por lo que no se les puede asignar el valor nulo. Su espacio de almacenamiento se libera automáticamente cuando se elimina el marco de pila que los contiene.


















