¿Dónde se almacenan los métodos estáticos y las variables estáticas en Java?
Por ejemplo:
class A {
static int i=0;
static int j;
static void method() {
// static k=0; can't use static for local variables only final is permitted
// static int L;
}
}
¿Dónde se almacenarán estas variables en Java, en el montón o en la memoria de pila? ¿Cómo se almacenan?
Los métodos estáticos (de hecho, todos los métodos), así como las variables estáticas, se almacenan en la PermGen
sección del montón, ya que son parte de los datos de reflexión (datos relacionados con la clase, no relacionados con la instancia). A partir de Java 8, PermGen ha sido reemplazado por MetaSpace y según JEP 122 solo contiene metadatos mientras los campos estáticos se almacenan en el montón.
Tenga en cuenta que esto se aplica principalmente a Hotspot JVM de Oracle y otros que se basan en él. Sin embargo, no todas las JVM tienen PermGen o Metaspace como Eclipse OpenJ9 .
Actualización para aclarar :
Tenga en cuenta que sólo las variables y sus valores técnicos (primitivas o referencias) se almacenan en el espacio PermGen.
Si su variable estática es una referencia a un objeto, ese objeto en sí se almacena en las secciones normales del montón (generación joven/vieja o espacio de superviviente). Esos objetos (a menos que sean objetos internos como clases, etc.) no se almacenan en el espacio PermGen.
Ejemplo:
static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.
Unas palabras sobre la recogida de basura:
No confíe en él ,finalize()
ya que no está garantizado su funcionamiento. Depende totalmente de la JVM decidir cuándo ejecutar el recolector de basura y qué recolectar, incluso si un objeto es elegible para la recolección de basura.
Por supuesto, puede establecer una variable estática en nula y así eliminar la referencia al objeto en el montón, pero eso no significa que el recolector de basura la recolectará (incluso si no hay más referencias).
Además finalize()
, se ejecuta solo una vez, por lo que debe asegurarse de que no genere excepciones ni impida que se recopile el objeto. Si detiene la finalización mediante alguna excepción, finalize()
no se invocará en el mismo objeto por segunda vez.
Una nota final : la forma en que se almacenan el código, los datos de tiempo de ejecución, etc. depende de la JVM que se utilice, es decir, HotSpot puede hacerlo de manera diferente a JRockit y esto puede incluso diferir entre versiones de la misma JVM. Lo anterior se basa en HotSpot para Java 5 y 6 (esos son básicamente iguales) ya que al momento de responder diría que la mayoría de la gente usaba esas JVM. Debido a cambios importantes en el modelo de memoria a partir de Java 8, es posible que las afirmaciones anteriores no sean ciertas para Java 8 HotSpot, y no verifiqué los cambios de Java 7 HotSpot, así que supongo que lo anterior sigue siendo cierto para esa versión. pero no estoy seguro aquí.
Antes de Java 8:
Las variables estáticas se almacenaron en el espacio permgen (también llamado área de método).
El espacio PermGen también se conoce como área de método.
PermGen Space solía almacenar 3 cosas.
- Datos a nivel de clase (metadatos)
- cuerdas internadas
- variables estáticas
Desde Java 8 en adelante
Las variables estáticas se almacenan en el propio Heap. Desde Java 8 en adelante, se eliminó el espacio PermGen y se introdujo un nuevo espacio denominado MetaSpace, que ya no forma parte del Heap, a diferencia del espacio Permgen anterior. Meta-Space está presente en la memoria nativa (memoria proporcionada por el sistema operativo a una aplicación particular para su propio uso) y ahora solo almacena los metadatos de la clase.
Las cadenas internas y las variables estáticas se mueven al propio montón.
Para obtener información oficial, consulte: JEP 122: Eliminar el espacio de generación permanente