¿Cómo se divide el grupo de memoria de Java?

224

Actualmente estoy monitoreando una aplicación Java con jconsole. La pestaña de memoria le permite elegir entre:

Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”

Cuál es la diferencia entre ellos ?

Dani Cricco
fuente
Suponiendo que está utilizando Sun JDK, la mejor respuesta se encontrará en su documentación: Tuning Garbage Collection (JDK 1.5) y Garbage Collection FAQ (JDK 1.4)
kdgregory

Respuestas:

327

Memoria del montón

La memoria de almacenamiento dinámico es el área de datos de tiempo de ejecución desde la cual la máquina virtual Java asigna memoria para todas las instancias y matrices de clase. El montón puede ser de un tamaño fijo o variable. El recolector de basura es un sistema automático de administración de memoria que reclama la memoria de almacenamiento dinámico para los objetos.

  • Eden Space : el grupo desde el cual se asigna inicialmente la memoria para la mayoría de los objetos.

  • Survivor Space : el grupo que contiene objetos que han sobrevivido a la recolección de basura del espacio Eden.

  • Tenured Generation o Old Gen : el grupo que contiene objetos que han existido durante algún tiempo en el espacio del sobreviviente.

Memoria sin almacenamiento dinámico

La memoria sin almacenamiento dinámico incluye un área de método compartida entre todos los subprocesos y la memoria requerida para el procesamiento interno u optimización para la máquina virtual Java. Almacena estructuras por clase, como un grupo constante de tiempo de ejecución, datos de campo y método, y el código para métodos y constructores. El área del método es lógicamente parte del montón pero, dependiendo de la implementación, una máquina virtual Java puede no recolectar basura o compactarla. Al igual que la memoria de almacenamiento dinámico, el área del método puede ser de tamaño fijo o variable. La memoria para el área de método no necesita ser contigua.

  • Generación permanente : el conjunto que contiene todos los datos reflectantes de la máquina virtual en sí, como los objetos de clase y método. Con máquinas virtuales Java que utilizan el intercambio de datos de clase, esta generación se divide en áreas de solo lectura y lectura-escritura.

  • Caché de código : HotSpot Java VM también incluye un caché de código, que contiene memoria que se utiliza para compilar y almacenar código nativo.

Aquí hay documentación sobre cómo usar Jconsole .

dfa
fuente
44
No estoy seguro de que @dfa sea completamente correcto, ya que la especificación de la máquina virtual Java establece claramente: "Aunque el área del método es lógicamente parte del montón, las implementaciones simples pueden elegir no recolectar basura o compactarla". Sin embargo, está claro que jconsole muestra la caché de código y la generación permanente como no heap, lo que parece contradecir la especificación. ¿Alguien puede dar más aclaraciones sobre esta contradicción?
James Bloom
@JamesBloom: me preguntaba lo mismo. Aunque la definición básica establece qué grupo de memoria pertenece a qué tipo (montón / no montón), ¿podría cambiar explícitamente el estado?
Umang Desai
2
el documento esto fue aparentemente robado de: docs.intergral.com/pages/viewpage.action?pageId=22478944 El documento contiene otra buena información sobre la JVM, vale la pena echarle un vistazo
Steve Siebert
1
A pesar de muchos votos a favor, en realidad no es una respuesta tan significativa. Por ejemplo, ¿qué significa "objetos que han sobrevivido a la recolección de basura del espacio Eden"? ¿Se trasladan estos objetos al Survivor Space desde Eden después de sobrevivir, o su espacio en Eden se considera como Survivor space? ¿Y qué pasa con la recolección de basura en piscinas que no sean el espacio Eden? Totalmente no claro.
Mikhail Batcer
y no te olvides de la pila (en el lado que no es el montón) :)
Toothless Seer
70

La nueva palabra clave asigna memoria en el montón de Java. El montón es el grupo principal de memoria, accesible para toda la aplicación. Si no hay suficiente memoria disponible para asignar ese objeto, la JVM intenta recuperar algo de memoria del montón con una recolección de elementos no utilizados. Si aún no puede obtener suficiente memoria, se lanza un OutOfMemoryError y se cierra la JVM.

El montón se divide en varias secciones diferentes, llamadas generaciones. A medida que los objetos sobreviven a más recolecciones de basura, son promovidos a diferentes generaciones. Las generaciones más viejas no son recolectadas con tanta frecuencia. Debido a que estos objetos ya han demostrado tener una vida más larga, es menos probable que se recolecten basura.

Cuando los objetos se construyen por primera vez, se asignan en el espacio Eden. Si sobreviven a una recolección de basura, son promovidos a Survivor Space, y si viven lo suficiente allí, se asignan a la Generación Tenida. Esta generación es basura recolectada con mucha menos frecuencia.

También hay una cuarta generación, llamada Generación Permanente, o PermGen. Los objetos que residen aquí no son elegibles para la recolección de elementos no utilizados y, por lo general, contienen un estado inmutable necesario para que se ejecute la JVM, como las definiciones de clase y el conjunto constante de cadenas. Tenga en cuenta que se planea eliminar el espacio PermGen de Java 8 y se reemplazará con un nuevo espacio llamado Metaspace, que se guardará en la memoria nativa. referencia :http://www.programcreek.com/2013/04/jvm-run-time-data-areas/

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Pythoner
fuente
El diagrama parece muy explicativo ... ¿Es válido para cualquier algoritmo GC? G1 tiene un conjunto diferente.
Venkateswara Rao
@Pythoner Creo que la bandera en púrpura oscuro debería ser -XX:PermSizey no -XX:MaxPermSizecomo ya se definió anteriormente.
Anurag
35

Con Java8, la región sin almacenamiento dinámico ya no contiene PermGen, pero Metaspace, que es un cambio importante en Java8, se supone que elimina los errores de memoria con java, ya que el tamaño de metaspace puede aumentarse dependiendo del espacio requerido por jvm para los datos de clase.

usuario2767149
fuente
1
En realidad, hay metaspace y espacio de clase: docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/…
mrswadge
23

Memoria de almacenamiento dinámico de Java es parte de la memoria asignada a JVM por el sistema operativo.

Los objetos residen en un área llamada el montón. El montón se crea cuando se inicia la JVM y puede aumentar o disminuir de tamaño mientras se ejecuta la aplicación. Cuando el montón se llena, se recolecta la basura.

ingrese la descripción de la imagen aquí

Puede encontrar más detalles sobre Eden Space, Survivor Space, Tenured Space y Permanent Generation en la siguiente pregunta SE:

Generación joven, titular y permanente

PermGen ha sido reemplazado por Metaspace desde el lanzamiento de Java 8.

En cuanto a sus consultas:

  1. Eden Space, Survivor Space, Tenured Space son parte de la memoria del montón
  2. Metaspace y Code Cache son parte de la memoria no heap.

Codecache: Java Virtual Machine (JVM) genera código nativo y lo almacena en un área de memoria llamada codecache. La JVM genera código nativo por una variedad de razones, que incluyen el bucle de intérprete generado dinámicamente, los apéndices de la Interfaz nativa de Java (JNI) y los métodos de Java compilados en código nativo por el compilador JIT. El JIT es, con mucho, el mayor usuario del codecache.

Ravindra babu
fuente