¿Dónde se almacenan los campos primitivos?
Los campos primitivos se almacenan como parte del objeto que se instancia en alguna parte . La forma más fácil de pensar dónde está esto es el montón. Sin embargo , este no es siempre el caso. Como se describe en la teoría y práctica de Java: Leyendas del rendimiento urbano, revisado :
Las JVM pueden usar una técnica llamada análisis de escape, mediante la cual pueden decir que ciertos objetos permanecen confinados en un solo subproceso durante toda su vida útil, y que la vida útil está limitada por la vida útil de un marco de pila determinado. Dichos objetos se pueden asignar de forma segura en la pila en lugar del montón. Aún mejor, para objetos pequeños, la JVM puede optimizar la asignación por completo y simplemente elevar los campos del objeto en registros.
Por lo tanto, más allá de decir "el objeto se crea y el campo también está allí", no se puede decir si hay algo en el montón o en la pila. Tenga en cuenta que para los objetos pequeños y de corta duración, es posible que el 'objeto' no exista en la memoria como tal y en su lugar puede tener sus campos colocados directamente en los registros.
El artículo concluye con:
Las JVM son sorprendentemente buenas para descubrir cosas que solíamos suponer que solo el desarrollador podía saber. Al permitir que la JVM elija entre la asignación de la pila y la asignación del montón en una base de caso por caso, podemos obtener los beneficios de rendimiento de la asignación de la pila sin hacer que el programador agonice sobre si asignar en la pila o en el montón.
Por lo tanto, si tiene un código similar al siguiente:
void foo(int arg) {
Bar qux = new Bar(arg);
...
}
donde ...
no permite qux
salir de ese alcance, qux
puede asignarse en la pila en su lugar. En realidad, esto es una victoria para la máquina virtual porque significa que no es necesario que se recolecte basura, desaparecerá cuando salga del alcance.
Más sobre análisis de escape en Wikipedia. Para aquellos dispuestos a profundizar en los documentos, Escape Analysis for Java de IBM. Para aquellos que vienen de un mundo de C #, pueden encontrar buenas lecturas de The Stack Is An Implementation Detail y The Truth About Value de Eric Lippert (son útiles para los tipos de Java, ya que muchos de los conceptos y aspectos son iguales o similares) . ¿Por qué los libros .Net hablan de la asignación de memoria de pila frente a pila? También entra en esto.
En los porqués de la pila y el montón
En el montón
Entonces, ¿por qué tener la pila o el montón? Para las cosas que dejan alcance, la pila puede ser costosa. Considera el código:
void foo(String arg) {
bar(arg);
...
}
void bar(String arg) {
qux(arg);
...
}
void qux(String arg) {
...
}
Los parámetros también son parte de la pila. En el caso de que no tenga un montón, estaría pasando el conjunto completo de valores en la pila. Esto está bien para "foo"
cadenas pequeñas ... pero qué pasaría si alguien colocara un archivo XML enorme en esa cadena. Cada llamada copiaría toda la cadena enorme en la pila, y eso sería un desperdicio.
En cambio, es mejor colocar los objetos que tienen algo de vida fuera del alcance inmediato (pasados a otro alcance, atrapados en una estructura que alguien más está manteniendo, etc.) en otra área que se llama el montón.
En la pila
No necesitas la pila. Uno podría, hipotéticamente, escribir un lenguaje que no use una pila (de profundidad arbitraria). Un viejo BASIC que aprendí en mi juventud lo hizo, uno solo podía hacer 8 niveles de gosub
llamadas y todas las variables eran globales, no había pila.
La ventaja de la pila es que cuando tiene una variable que existe con un ámbito, cuando abandona ese ámbito, se abre el marco de la pila. Realmente simplifica lo que hay y lo que no. El programa pasa a otro procedimiento, un nuevo marco de pila; el programa vuelve al procedimiento y usted vuelve al que ve su alcance actual; el programa deja el procedimiento y todos los elementos de la pila se desasignan.
Esto realmente facilita la vida de la persona que escribe el tiempo de ejecución para que el código use una pila y un montón. Simplemente tienen muchos conceptos y formas de trabajar en el código, lo que permite a la persona que escribe el código en el idioma liberarse de pensar explícitamente en ellos.
La naturaleza de la pila también significa que no puede fragmentarse. La fragmentación de la memoria es un problema real con el montón. Asigne algunos objetos, luego la basura recolecte uno del medio y luego intente encontrar espacio para asignar el siguiente grande. Es un desastre. Ser capaz de poner cosas en la pila significa que no tienes que lidiar con eso.
Cuando algo es basura recolectada
Cuando algo es basura recolectada, se va. Pero es solo basura recolectada porque ya se ha olvidado: no hay más referencias al objeto en el programa a las que se pueda acceder desde el estado actual del programa.
Señalaré que esta es una simplificación muy grande de la recolección de basura. Hay muchos recolectores de basura (incluso dentro de Java; puede ajustar el recolector de basura mediante el uso de varias banderas ( documentos ). Estos se comportan de manera diferente y los matices de cómo cada uno hace las cosas son demasiado profundos para esta respuesta. Es posible que desee leer Conceptos básicos de Java Garbage Collection para tener una mejor idea de cómo funciona algo de eso.
Dicho esto, si algo se asigna en la pila, no es basura recolectada como parte de System.gc()
él, se desasigna cuando aparece el marco de la pila. Si hay algo en el montón y se hace referencia desde algo en la pila, no se recolectará basura en ese momento.
¿Por qué importa esto?
En su mayor parte, su tradición. Los libros de texto escritos y las clases de compilación y la documentación de varios bits hacen un gran negocio sobre el montón y la pila.
Sin embargo, las máquinas virtuales de hoy (JVM y similares) han hecho todo lo posible para tratar de mantener esto oculto al programador. A menos que se esté quedando sin uno u otro y necesite saber por qué (en lugar de simplemente aumentar el espacio de almacenamiento de manera adecuada), no importa demasiado.
El objeto está en algún lugar y está en el lugar donde se puede acceder de forma correcta y rápida durante el tiempo adecuado que existe. Si está en la pila o en el montón, realmente no importa.