Conozco el concepto de un grupo de constantes y el grupo de constantes de cadena utilizado por las JVM para manejar literales de cadena. Pero no sé qué tipo de memoria utiliza la JVM para almacenar literales constantes de cadena. ¿La pila o el montón? Dado que es un literal que no está asociado con ninguna instancia, asumiría que se almacenará en la pila. Pero si no es referido por ninguna instancia, el literal debe ser recopilado por GC run (corríjame si me equivoco), entonces, ¿cómo se maneja eso si está almacenado en la pila?
104
Respuestas:
La respuesta es técnicamente ninguna de las dos. Según la especificación de la máquina virtual de Java, el área para almacenar literales de cadena está en el grupo de constantes de tiempo de ejecución . El área de memoria del grupo constante de tiempo de ejecución se asigna por clase o por interfaz, por lo que no está vinculada a ninguna instancia de objeto. El grupo de constantes de tiempo de ejecución es un subconjunto del área de métodos que "almacena estructuras por clase, como el grupo de constantes de tiempo de ejecución, datos de campo y método, y el código para métodos y constructores, incluidos los métodos especiales utilizados en la inicialización e interfaz de clases e instancias. tipo de inicialización ". La especificación de VM dice que aunque el área de método es lógicamente parte del montón, no dicta que la memoria asignada en el área de método esté sujeta a la recolección de basura u otros comportamientos que se asociarían con las estructuras de datos normales asignadas al montón.
fuente
Como se explica en esta respuesta , la ubicación exacta del grupo de cadenas no se especifica y puede variar de una implementación de JVM a otra.
Es interesante notar que hasta Java 7, el grupo estaba en el espacio permgen del montón en JVM de hotspot pero se ha movido a la parte principal del montón desde Java 7 :
Y en Java 8 Hotspot, la generación permanente se ha eliminado por completo.
fuente
Los literales de cadena no se almacenan en la pila. Nunca. De hecho, no se almacenan objetos en la pila.
Los literales de cadena (o más exactamente, los objetos de cadena que los representan)
sealmacenaron históricamente en un montón llamado montón "permgen". (Permgen es la abreviatura de generación permanente).En circunstancias normales, los literales String y gran parte del resto del contenido del montón de permgen son accesibles "permanentemente" y no se recolectan como basura. (Por ejemplo, los literales de cadena siempre son accesibles desde los objetos de código que los usan). Sin embargo, puede configurar una JVM para intentar buscar y recolectar clases cargadas dinámicamente que ya no son necesarias, y esto puede hacer que los literales de cadena se recolecten como basura .
ACLARACIÓN # 1 - No estoy diciendo que Permgen no reciba GC'ed. Lo hace, normalmente cuando la JVM decide ejecutar un GC completo. Mi punto es que los literales de cadena serán accesibles siempre que el código que los usa sea accesible, y el código será accesible siempre que se pueda acceder al cargador de clases del código, y para los cargadores de clases predeterminados, eso significa "para siempre".
ACLARACIÓN # 2 - De hecho, Java 7 y versiones posteriores usan el montón regular para contener el grupo de cadenas. Por lo tanto, los objetos String que representan los literales String y las cadenas internas están en realidad en el montón normal. (Vea la respuesta de @ assylias para más detalles).
No hay una "línea delgada". Es realmente muy simple:
String
los objetos que representan / corresponden a cadenas literales se mantienen en el grupo de cadenas.String
los objetos que fueron creados por unaString::intern
llamada se mantienen en el grupo de cadenas.String
objetos NO se mantienen en el grupo de cuerdas.Luego está la pregunta separada de dónde se "almacena" el grupo de cadenas. Antes de Java 7, era el montón de permgen. Desde Java 7 en adelante, es el montón principal.
fuente
Agrupación de cadenas
String.intern () en Java 6
String.intern () en Java 7
Los valores del grupo de cadenas se recolectan como basura
fuente.
fuente
Como explican otras respuestas, la memoria en Java se divide en dos partes
1. Pila: se crea una pila por subproceso y almacena marcos de pila que nuevamente almacenan variables locales y si una variable es un tipo de referencia, entonces esa variable se refiere a una ubicación de memoria en el montón para el objeto real.
2. Montón: todo tipo de objetos se crearán únicamente en el montón.
La memoria del montón se vuelve a dividir en 3 porciones
1. Young Generation: almacena objetos que tienen una vida corta, Young Generation en sí se puede dividir en dos categorías Eden Space y Survivor Space .
2. Old Generation: Almacene objetos que han sobrevivido a muchos ciclos de recolección de basura y todavía se les hace referencia.
3. Generación permanente: almacena metadatos sobre el programa, por ejemplo, grupo de constantes en tiempo de ejecución.
El grupo de constantes de cadena pertenece al área de generación permanente de la memoria Heap.
Podemos ver el grupo de constantes en tiempo de ejecución para nuestro código en el código de bytes usando el
javap -verbose class_name
cual nos mostrará referencias de métodos (#Methodref), objetos de clase (#Class), literales de cadena (#String)Puede leer más sobre esto en mi artículo ¿Cómo maneja la JVM la sobrecarga y la anulación de métodos internamente ?
fuente
A las excelentes respuestas que ya se incluyen aquí, quiero agregar algo que falta en mi perspectiva: una ilustración.
Como ya, JVM divide la memoria asignada a un programa Java en dos partes. uno es pila y otro es montón . La pila se usa para fines de ejecución y el montón se usa para fines de almacenamiento. En esa memoria de pila, JVM asigna algo de memoria especialmente diseñada para cadenas literales. Esta parte de la memoria dinámica se denomina grupo de constantes de cadena .
Entonces, por ejemplo, si inicia los siguientes objetos:
String literales
s1
es2
irán al grupo de constantes de cadena, objetos obj1, obj2, obj3 al montón. Todos ellos, serán referenciados desde la Pila.Además, tenga en cuenta que "abc" aparecerá en el montón y en el grupo constante de cadenas. ¿Por qué se crea
String s1 = "abc"
yString obj1 = new String("abc")
se creará de esta manera? Es porqueString obj1 = new String("abc")
crea explícitamente una instancia nueva y referencialmente distinta de un objeto String yString s1 = "abc"
puede reutilizar una instancia del grupo de constantes de cadena si hay una disponible. Para una explicación más elaborada: https://stackoverflow.com/a/3298542/2811258fuente