asignación estática en java – stack, stack y generación permanente

Últimamente he estado leyendo mucho sobre esquemas de asignación de memoria en Java, y ha habido muchas dudas ya que he estado leyendo de varias fonts. Recogí mis conceptos y solicito revisar todos los puntos y comentarlos. Llegué a saber que la asignación de memoria es específica de JVM, así que debo decir de antemano, que mi pregunta es específica de Sun.

  1. Las clases (cargadas por los cargadores de clases) van en un área especial en montón: Generación permanente
  2. Toda la información relacionada con una clase como el nombre de la clase, las matrices de objetos asociadas con la clase, los objetos internos utilizados por JVM (como java / lang / Object) y la información de optimización van al área de generación permanente.
  3. Todas las variables de miembros estáticos se mantienen en el área de Generación permanente nuevamente.
  4. Los objetos van en un montón diferente: generación joven
  5. Solo hay una copia de cada método por clase, ya sea el método estático o no estático. Esa copia se coloca en el área de Generación permanente. Para los métodos no estáticos, todos los parámetros y variables locales van a la stack, y cada vez que hay una invocación concreta de ese método, obtenemos un nuevo stack-frame asociado a él. No estoy seguro de dónde se almacenan las variables locales de un método estático. ¿Están en el montón de la generación permanente? O solo su referencia se almacena en el área de Generación permanente, y la copia real está en otro lugar (¿Dónde?)
  6. Tampoco estoy seguro de dónde se almacena el tipo de devolución de un método.
  7. Si los objetos (en la generación joven) necesitan usar un miembro estático (en la generación permanente), se les da una referencia al miembro estático && se les da suficiente espacio de memoria para almacenar el tipo de retorno del método, etc.

¡Gracias por pasar esto!

En primer lugar, debe quedar claro para usted que hay muy pocas personas que puedan confirmar estas respuestas de un conocimiento de primera mano. Muy pocas personas han trabajado en las JVM recientes de HotSpot o las han estudiado hasta la profundidad necesaria para saber realmente. La mayoría de la gente aquí (yo incluido) está respondiendo en función de cosas que han visto escritas en otros lugares, o de lo que han deducido. Por lo general, lo que está escrito aquí, o en varios artículos y páginas web, se basa en otras fonts que pueden ser definitivas o no. A menudo es simplificado, inexacto o simplemente incorrecto.

Si desea una confirmación definitiva de sus respuestas, realmente necesita descargar el código fuente de OpenJDK … y hacer su propia investigación leyendo y comprendiendo el código fuente. Hacer preguntas sobre SO o rastrear artículos web al azar no es una técnica de investigación académica sólida.

Una vez dicho esto …

1) Las clases (cargadas por los cargadores de clases) van en un área especial en el montón: Generación permanente.

AFAIK, sí. ( Actualización : ver abajo)

2) Toda la información relacionada con una clase como el nombre de la clase, las matrices de objetos asociadas con la clase, los objetos internos utilizados por JVM (como java / lang / Object) y la información de optimización van al área de generación permanente.

Más o menos, sí. No estoy seguro de lo que quieres decir con algunas de esas cosas. Supongo que “los objetos internos utilizados por JVM (como java / lang / Object)” significa descriptores de clase internos de JVM.

3) Todas las variables de miembros estáticos se mantienen nuevamente en el área de Generación permanente.

Las variables en sí sí. Estas variables (como todas las variables de Java) contendrán valores primitivos o referencias a objetos. Sin embargo, mientras que las variables de miembro estático están en un marco que se asigna en el montón de permgen, los objetos / matrices a los que se refieren esas variables se pueden asignar en cualquier montón.

4) Los objetos van en un montón diferente: generación joven

No necesariamente. Los objetos grandes se pueden asignar directamente a la generación permanente.

5) Solo hay una copia de cada método por clase, ya sea el método estático o no estático. Esa copia se coloca en el área de Generación permanente.

Suponiendo que se refiere al código del método, entonces AFAIK sí. Aunque puede ser un poco más complicado. Por ejemplo, ese código puede existir en códigos de bytes y / o en formas de códigos nativos en diferentes momentos durante la vida de la JVM.

… Para los métodos no estáticos, todos los parámetros y las variables locales van a la stack, y cada vez que hay una invocación concreta de ese método, obtenemos un nuevo stack-frame asociado a él.

Sí.

… No estoy seguro de dónde se almacenan las variables locales de un método estático. ¿Están en el montón de la generación permanente? O solo su referencia se almacena en el área de Generación permanente, y la copia real está en otro lugar (¿Dónde?)

No. Se almacenan en la stack, al igual que las variables locales en métodos no estáticos.

6) Tampoco estoy seguro de dónde se almacena el tipo de devolución de un método.

Si se refiere al valor devuelto por una llamada a un método (no válido), entonces se devuelve en la stack o en un registro de máquina. Si se devuelve en la stack, toma 1 o 2 palabras, dependiendo del tipo de devolución.

7) Si los objetos (en la generación joven) necesitan usar un miembro estático (en la generación permanente), se les da una referencia al miembro estático && se les da suficiente espacio de memoria para almacenar el tipo de retorno del método, etc. .

Eso es inexacto (o al menos, no te estás expresando claramente).

Si algún método accede a una variable miembro estática, lo que obtiene es un valor primitivo o una referencia de objeto. Esto se puede asignar a una variable local o parámetro (existente), asignado a un miembro (existente) estático o no estático, asignado a un elemento (existente) de una matriz previamente asignada, o simplemente utilizado y descartado.

  • En ningún caso, el almacenamiento nuevo debe asignarse para mantener un valor primitivo o de referencia.

  • Normalmente, una palabra de memoria es todo lo que se necesita para almacenar un objeto o referencia de matriz, y un valor primitivo generalmente ocupa una o dos palabras, dependiendo de la architecture del hardware.

  • En ningún caso, el llamante debe asignar espacio para contener algún objeto / matriz devuelto por un método. En Java, los objetos y las matrices siempre se devuelven utilizando la semántica de pasar por valor … pero ese valor que se devuelve es un objeto o una matriz de referencia.

ACTUALIZAR

A partir de Java 8, el espacio PermGen ha sido reemplazado por Metaspace. Para obtener más información, consulte estos recursos:

  • ¿Cuál es la diferencia entre PermGen y Metaspace?
  • Java 8: de PermGen a Metaspace
  • Acerca de G1 Garbage Collector, Permanent Generation and Metaspace