[Java] JVM Aprendizaje (3)

La estructura general de la memoria de la JVM

本地方法栈

La función de la pila de métodos locales es similar a la de la pila de la máquina virtual Java.La pila de la máquina virtual Java se usa para administrar la invocación de funciones Java, mientras que la pila de métodos locales se usa para administrar la invocación de métodos locales. Pero los métodos nativos no están implementados en Java, sino en C (como el método Object.hashcode).

La pila de métodos nativos es un área muy similar a la pila de máquinas virtuales y su objeto de servicio es el método nativo. Incluso puede pensar en la pila de máquinas virtuales y la pila de métodos nativos como la misma área.

No hay disposiciones obligatorias en la especificación de la máquina virtual, y las máquinas virtuales de varias versiones se pueden implementar libremente. HotSpot combina directamente la pila de métodos locales y la pila de la máquina virtual en una sola.

方法区

El área de método (Method Area) es un área de memoria de tiempo de ejecución compartida por subprocesos. Almacena la información estructural de cada clase, como el grupo de constantes de tiempo de ejecución (grupo de constantes de tiempo de ejecución) y los datos del método, el contenido del código de bytes de los constructores y los métodos ordinarios, y también incluye algunos utilizados en la inicialización de clases, instancias e interfaces. método especial

El área de métodos es la "división lógica" de la memoria por la JVM. Antes de JDK1.7 y antes, muchos desarrolladores solían llamar al área de métodos “永久代”porque en la máquina virtual HotSpot, el diseñador usaba la generación permanente para implementar el distrito de métodos de especificación de JVM. . Usado en JDK1.8 y posteriores 元空间para implementar el área de métodos.

inserte la descripción de la imagen aquí

metaespacio

Similar al espacio de almacenamiento dinámico, el área de métodos también es un área de memoria compartida, por lo que el área de métodos es compartida por subprocesos. Si dos subprocesos intentan acceder a la misma información de clase en el área de métodos, y esta clase no se ha cargado en la JVM, entonces solo se permite que un subproceso la cargue en este momento y el otro debe esperar.

En la máquina virtual HotSpot y la versión de Java7, la variable estática y el conjunto de constantes de tiempo de ejecución de la generación permanente se han transferido al montón, y el resto se almacena en la memoria que no es de montón de la JVM, mientras que la versión de Java8 ha eliminado el permanente. generación implementada en el área de métodos, y reemplace la generación permanente anterior con metaespacio (metadatos de clase), y la ubicación de almacenamiento del metaespacio es la memoria local.

¿Por qué Java8 usa metaespacio en lugar de generación permanente y cuáles son los beneficios de hacerlo?

La explicación oficial es que
la eliminación de la generación permanente es un esfuerzo por integrar HotSpot JVM y JRockit VM, porque JRockit no tiene una generación permanente, por lo que no es necesario configurar la generación permanente.

La memoria de generación permanente suele ser insuficiente o se produce un desbordamiento de la memoria y se lanza una excepción java.lang.OutOfMemoryError: PermGen. Esto se debe a que en la versión JDK1.7, el tamaño del área PermGen especificada es de 8 M. Dado que la información de metadatos de las clases en PermGen se puede recopilar cada vez que FullGC, la tasa de recuperación es baja y los resultados no son satisfactorios; También es difícil determinar cuánto espacio asignar para PermGen. El tamaño de PermSize depende de muchos factores, como el número total de clases cargadas por la JVM, el tamaño del grupo constante y el tamaño del método.

grupo de constantes de tiempo de ejecución

El grupo de constantes de tiempo de ejecución (Runtime Constant Pool) es la representación en tiempo de ejecución del grupo de constantes (Constant_Pool) de cada clase o interfaz, que incluye varias constantes diferentes: desde literales numéricos conocidos en tiempo de compilación hasta aquellos que deben analizarse en tiempo de ejecución Un método o solo se puede obtener la referencia de campo.

El conjunto de constantes de tiempo de ejecución forma parte del área de métodos. Otra característica importante del grupo de constantes de tiempo de ejecución en relación con el grupo de constantes de clase es que es dinámico.

montón

El montón es el área de memoria más grande en la JVM, y casi todos los objetos que solicitamos se almacenan aquí. A menudo decimos recolección de basura, el objeto de la operación es el montón.

El espacio de almacenamiento dinámico generalmente se solicita cuando se inicia el programa, pero no necesariamente se utilizará todo. Por lo general, el almacenamiento dinámico está configurado para ser escalable.

Con la creación frecuente de objetos, se ocupa cada vez más espacio de montón y es necesario reciclar los objetos no utilizados de vez en cuando. Esto se llama GC (recolección de basura) en Java.

Cuando se crea ese objeto, ¿se asigna en el montón o en la pila? Esto tiene que ver con dos cosas: el tipo del objeto y dónde existe en la clase Java.

Los objetos de Java se pueden dividir en tipos de datos básicos y objetos ordinarios.

Para 普通对象Java, la JVM primero creará el objeto en el montón y luego usará su referencia en otro lugar. Por ejemplo, guarde esta referencia en la tabla de variables locales de la pila de la máquina virtual.

Para 基本数据类型(byte, short, int, long, float, double, char), hay dos casos.
Cuando declara un objeto de un tipo de datos primitivo en el cuerpo de un método, se asigna directamente en la pila. En otros casos, se asigna en el montón.

Memoria directa (memoria fuera del montón)

La memoria directa tiene un nombre más científico, memoria fuera del montón.

Cuando la JVM se está ejecutando, solicitará una gran cantidad de memoria del sistema operativo para almacenar datos; al mismo tiempo, hay pilas de máquinas virtuales, pilas de métodos locales y contadores de programas, que se denominan áreas de pila. La memoria restante del sistema operativo es memoria fuera del montón.

No es parte del área de datos cuando la máquina virtual se está ejecutando, ni es el área de memoria definida en la especificación de la máquina virtual Java; si se usa NIO, esta área se usará con frecuencia y se puede hacer referencia directa al objeto directByteBuffer y operado en el montón de Java;

Esta parte de la memoria no está limitada por el tamaño del montón de Java, pero está limitada por la memoria total de la máquina, que se puede configurar con -XX:MaxDirectMemorySize (el valor predeterminado es el mismo que el valor máximo de la memoria del montón) , por lo que también se producirán excepciones OOM.

El proceso general de la memoria de ejecución de JVM

La JVM se inicia en el sistema operativo, solicita memoria, primero inicializa el área de datos de tiempo de ejecución, luego carga la clase en el área de método y finalmente ejecuta el método.

El proceso de ejecución y salida del método se refleja en la memoria como el apilamiento y la extracción de marcos de pila en la pila de la máquina virtual.

Al mismo tiempo, los objetos creados durante la ejecución del método generalmente se colocan en el montón y, finalmente, los objetos en el montón también deben limpiarse mediante la recolección de elementos no utilizados.

Particionamiento generacional del espacio de almacenamiento dinámico

El montón se divide en 新生代y 老年代(Tenured), la nueva generación se divide en áreas Eden y Survivor, y finalmente Survivor se compone de From Survivor y To Survivor.

inserte la descripción de la imagen aquí

CG

La recolección de basura (GC) en la JVM (Java Virtual Machine) es un mecanismo automático de administración de memoria que se usa para recuperar automáticamente el espacio de memoria ocupado por objetos que ya no se usan en tiempo de ejecución. El recolector de basura es responsable de identificar y reclamar esos objetos inválidos o inaccesibles, y reasignar la memoria que ocupan a otros objetos que los necesitan.

sin memoria

Cuando se produce un desbordamiento de memoria (memoria insuficiente) cuando la JVM se está ejecutando, normalmente se puede subdividir en los siguientes tipos: desbordamiento de pila, desbordamiento de pila, desbordamiento de área de método y desbordamiento de memoria directa nativa.

堆溢出(Heap Overflow):
El montón es el área de memoria en la JVM utilizada para almacenar instancias de objetos. Se produce un desbordamiento de almacenamiento dinámico cuando el número de objetos creados supera la capacidad del almacenamiento dinámico o cuando no se puede asignar espacio de memoria para objetos nuevos. La causa común del desbordamiento del montón es la fuga de memoria (Memory Leak), es decir, se hace referencia continuamente a una gran cantidad de objetos inútiles y el recolector de elementos no utilizados no puede recuperarlos.

栈溢出(Stack Overflow):
La pila es el área de memoria en la JVM que se utiliza para contener llamadas a métodos y variables locales. Cada subproceso tendrá su propia pila para almacenar el estado de las llamadas a métodos. Cuando la llamada recursiva o el nivel de llamada al método es demasiado profundo, el tamaño de la pila excederá su capacidad, lo que provocará un desbordamiento de la pila. Un desbordamiento de pila podría deberse a una recursividad infinita o a un método que sigue llamándose a sí mismo sin una condición de terminación.

方法区溢出(Method Area Overflow):
El área de método es un área de memoria en la JVM que se utiliza para almacenar datos como información de clase, constantes, variables estáticas y código optimizado por el compilador. Cuando se cargan demasiadas clases o el número de constantes en el conjunto de constantes excede el límite del área del método, puede causar que el área del método se desborde. Además, demasiadas clases generadas dinámicamente también pueden provocar un desbordamiento del área de método.

本机直接内存溢出(Direct Memory Overflow):
La memoria directa nativa es un área de memoria directa utilizada por la JVM que está separada de la memoria del montón. Cuando se utilizan búferes directos a través de NIO, se utiliza la memoria directa nativa. Si continúa asignando memoria directa nativa sin reclamarla, después de alcanzar el límite del sistema operativo para la memoria directa, se producirá un error de desbordamiento de memoria directa nativa.

Cuando ocurren estos problemas de desbordamiento, generalmente se lanzan las excepciones correspondientes, por ejemplo: OutOfMemoryError, StackOverflowError, etc.

Supongo que te gusta

Origin blog.csdn.net/qq_43358469/article/details/131391031
Recomendado
Clasificación