2010-03-15 20 views
46

La memoria del montón es basura recolectada en Java.¿La basura acumulada se recoge en Java?

¿También se recoge la basura de la pila?

¿Cómo se recupera la memoria de pila?

+10

La pila es el algoritmo original de recolección de basura. ¡Incluso C tiene una pila recolectada de basura! – jrockway

+0

C, C++, Java tiene una colección de basura apilada. Aparte de eso, solo Java proporciona una gran cantidad de recolección de basura. (de los tres mencionados anteriormente) –

Respuesta

28

La pila no es basura recolectada en Java.

La pila asignada para una llamada de método dada se libera cuando el método retorna. Dado que se trata de una estructura LIFO muy simple, no hay necesidad de recolección de basura.

Un lugar donde la pila y la recolección de basura interactúan es que las referencias en la pila son raíces de GC (lo que significa que son las referencias de raíz de las cuales se decide la accesibilidad).

+11

Para ser precisos, la pila no contiene nada que pueda recogerse como basura. Las únicas cosas que contiene son referencias a objetos y valores de tipos primitivos. Lo único que está sujeto a la recolección de basura son los objetos. Tenga en cuenta la diferencia entre un objeto y una referencia a él. –

+0

@Roland: eso es lo que dije. Las raíces de GC son * referencias *, no los objetos. –

+0

Lo sé. Solo pensé que para la redacción de esta pregunta, sería bueno ser muy explícito sobre este tema y explicarlo quizás más de lo necesario. –

32

La memoria en la pila contiene parámetros de método y variables locales (para ser precisos: las referencias de objetos y variables para tipos primitivos). Eso se eliminará automáticamente si abandona el método. Si las variables son referencias (a objetos), los objetos están en el montón y son manejados por el recolector de basura.

Por lo tanto, la pila no se recolecta de la misma manera que el montón, pero la pila es una forma de administración de memoria automática propia (que es anterior a la recolección de basura).

A more detailed answer is given by Thomas Pornin, investigue eso para más detalles.

0

Nadie, los datos se extraen y saltan de la pila ya que tiene variables internas en los métodos, durante las llamadas a métodos, etc. No es necesario que se preocupe por esto.

8

La parte de la pila de la memoria funciona igual que una "pila". Sé que suena mal, pero así es exactamente como funciona. Los datos se agregan a la parte superior, uno encima del otro (pushed onto the stack) y se eliminan automáticamente de la parte superior (popped off the stack) mientras se ejecuta el programa. No es basura recolectada, y no es necesario, ya que esa memoria se recupera automáticamente una vez que los datos se extraen de la pila. Y cuando digo reclamado, no me refiero a que se desasigne, es solo que la ubicación en la memoria de la pila donde se almacenarán los próximos datos disminuye, a medida que los datos se quitan.

Por supuesto, eso no quiere decir que no tenga que preocuparse en absoluto de la pila. Si ejecuta una función recursiva muchas veces, eventualmente agotará todo el espacio de la pila. Lo mismo si llama a muchas funciones, especialmente si tienen muchos parámetros y/o variables locales.

Pero la cuestión fundamental es que la memoria de la pila se usa y se recupera cuando las funciones entran y salen del alcance automáticamente. Entonces, al final de la ejecución de su programa, toda la memoria de la pila sería gratuita y luego se devolvería al sistema operativo.

1

Todos los objetos en Java se asignan en el montón. (Al menos en cuanto a la especificación, la implementación real puede asignarlos en la pila si se comportan de forma transparente como si estuvieran en el montón).

Lo que es coleccionable es un poco sutil. Si la única referencia a un objeto está en un único marco de pila, y se puede mostrar que la referencia no se usará nuevamente, entonces el objeto puede ser recolectado. Si el objeto solo se usa para leer un campo, entonces esa lectura de campo puede optimizarse hacia adelante y el objeto recolectado antes de lo que cabría esperar.

Esto no suele importar a menos que esté utilizando finalizadores (o presumiblemente Reference s).En ese caso, debe tener cuidado y usar bloqueos/volátiles para forzar una relación happens-before.

Cuando los subprocesos se detienen, normalmente la pila completa se desasignará.

1

Todo lo que se encuentra en la pila es tratado como raíces globales por un recolector de basura. Entonces, sí, definitivamente puedes decir que la pila es "basura recolectada".

14

La pila podría ser basura recogida. Sin embargo, en la mayoría de las implementaciones de JVM, se maneja como, bueno, una "pila", que por definición no permite la recolección de basura.

Lo que llamamos la pila es la acumulación de activación método contextos: para cada método invocado, esto es la estructura conceptual que contiene los argumentos del método, las variables locales, un puntero oculto al contexto para el método de llamada, y un espacio para guardar el puntero de instrucción. El contexto de activación no es accesible como tal desde el lenguaje Java en sí. Un contexto se vuelve inútil cuando el método sale (con un return o debido a una excepción arrojada). Ocurre que cuando un método A llama a un método B, se garantiza que cuando A recupera el control, el contexto para B se vuelve inútil. Esto implica que la duración del contexto para B es un subrango del tiempo de vida del contexto para A. Por lo tanto, los contextos de activación (para un hilo dado) pueden asignarse con una disciplina LIFO ("último en entrar, primero en salir"). En palabras más simples, una pila: un nuevo contexto de activación se coloca en la parte superior de la pila de contextos, y el contexto en la parte superior será el primero en eliminarse.

En la práctica, los contextos de activación (también llamados cuadros de pila ) se concatenan, en orden de apilamiento, en un área dedicada. Esa área se obtiene del sistema operativo cuando se inicia el subproceso y el sistema operativo la recupera cuando finaliza el subproceso. La parte superior de la pila está designada por un puntero específico, a menudo incluido en un registro de la CPU (esto depende de si la JVM está interpretando o compilando el código). El "puntero al contexto de la persona que llama" es virtual; el contexto del que llama se encuentra necesariamente justo debajo en orden de pila. El GC no interviene: el área de la pila se crea y recupera de forma síncrona, a partir de la actividad de la hebra en sí misma. Esta es también la forma en que funciona en muchos idiomas, como C, que no tienen un GC en absoluto.

Ahora nada impide que una implementación de JVM haga lo contrario, p. Ej. asignando contextos de activación en el montón y haciéndolos recolectar por el GC. Esto no suele hacerse en Java Virtual Machines ya que la asignación de la pila es más rápida. Pero algunos otros lenguajes necesitan hacer tales cosas, más notablemente aquellos que juegan con continuations mientras todavía usan un GC (por ejemplo, Scheme y su función call-with-current-continuation), porque tales juegos rompen la regla LIFO explicada anteriormente.

+0

+1 para distinguir realmente contextos y pilas de activación de métodos. – sleske

+0

También vale la pena señalar que en algunas plataformas (especialmente en sistemas integrados) los punteros de instrucciones guardadas entran en un área de almacenamiento completamente diferente de los argumentos de funciones, variables locales, etc. Para programas que nunca utilizan llamadas de función indirectas (cierto de muchos incrustados sistemas), esto puede proporcionar una protección sustancial contra la ejecución de código erróneo. Además, dicho diseño puede acelerar las cosas al evitar la necesidad de gastar ciclos de memoria al guardar o volver a cargar el contador del programa en la entrada/salida de función (una pila de hardware funciona directamente en el contador de programa omitiendo el bus de memoria). – supercat

4

Si se refiere a la memoria utilizada en la pila, no es basura.
La máquina virtual java utiliza instrucciones explícitas de bytecode para reservar y liberar memoria en la pila, estas instrucciones son generadas por el compilador y administran la vida útil de primitivas como int, boolean, double y referencias de objeto en la pila.
Ha habido planes para implementar una llamada optimización de cola de llamadas, que eliminaría algunas entradas de la pila una vez que se sabe que ya no se usan, pero no conozco ninguna JVM que ya sea compatible con esto.
Así que no, no hay recolección de basura para la pila, solo el compilador generó instrucciones push y pop para administrar el uso de la memoria.

La pila en sí es parte de un hilo. La pila se asigna cuando se crea el objeto de subproceso y se recoge la basura después de que finaliza el subproceso y ya no se hace referencia al objeto de subproceso.

0

No. La pila no es basura recogida en Java. Cada hilo tiene su propia pila y contiene:

  1. valores método específico (que son de corta duración) y
  2. referencias a los objetos, creado en el montón, y se están referido por el método

Estos valores se envían como marcos de pila a la pila para cada llamada de método. Dado que la pila sigue el orden 'Last-in-First-out', al final de cada llamada a un método, cada cuadro de pila que contiene todos los datos específicos del método y las referencias a los objetos, si los hay, se abren.

Por lo tanto, los datos en la pila se limpian automáticamente una vez que el método/programa queda fuera del alcance.

Cuestiones relacionadas