Conocimiento de JVM que la entrevista debe preguntar: aprendizaje de funciones de JVM

Área de datos en tiempo de ejecución

Durante la ejecución del programa Java, la máquina virtual Java divide la memoria que administra en varias áreas diferentes, estas áreas tienen sus propios fines, así como el tiempo de creación y destrucción, y algunas áreas continúan iniciando con el proceso de la máquina virtual. Existen, algunas áreas se crean y destruyen según el inicio y el final de los hilos del usuario. La memoria administrada por la máquina virtual Java incluye las siguientes áreas.

Partición de memoria

La parte sombreada es el área de datos compartida por todos los subprocesos, y la parte no sombreada es el área de datos aislada de subprocesos.

Contador de programa

El Program Counter Register es un pequeño espacio de memoria, que puede ser considerado como el indicador de número de línea del bytecode ejecutado por el hilo actual.El intérprete de bytecode se selecciona cambiando el valor de este contador cuando funciona. La siguiente instrucción de código de bytes que debe ejecutarse es un indicador del flujo de control del programa. Las funciones básicas como bifurcación, bucle, salto, manejo de excepciones y recuperación de subprocesos deben depender de este contador para completarse.

En cualquier momento, un procesador solo puede ejecutar instrucciones en un hilo. Para volver a la posición correcta después del cambio de hilo, cada hilo debe tener un contador de programa independiente, y los contadores entre los hilos no se afectan entre sí. Por lo tanto, el espacio de memoria del contador de programa es privado para cada hilo.

También tenga en cuenta: cuando el hilo está ejecutando un método Java, este contador registra la dirección de la instrucción de código de bytes de la máquina virtual que se está ejecutando; cuando el hilo está ejecutando un método nativo, el valor del contador debe estar vacío (Indefinido). Y esta área de memoria no aparecerá como OutOfMemoryError.

Pila de máquinas virtuales Java

La pila de máquinas virtuales de Java es privada para el hilo y su ciclo de vida es el mismo que el del hilo. Cuando se ejecuta cada método, la máquina virtual Java creará sincrónicamente un marco de pila (marco de pila) para almacenar información como la tabla de variables locales, la pila de operandos, la conexión dinámica y la salida del método . El proceso desde que se llama a cada método hasta la finalización de la ejecución corresponde al proceso de un marco de pila desde el empuje hasta la aparición en la pila de la máquina virtual.

Pila de máquinas virtuales Java

La tabla de variables locales almacena los tipos de datos básicos (booleano, byte, char, short, int, float, long, double) y referencias de objetos de la máquina virtual Java que se pueden conocer en tiempo de compilación.

La memoria requerida por la tabla de variables locales se asigna durante la compilación, y el tamaño de la tabla de variables locales no cambiará durante la ejecución del método.

Si la profundidad de la pila solicitada por el hilo es mayor que la profundidad permitida por la máquina virtual, se lanzará una excepción StackOverflowError; si la capacidad de la pila de la máquina virtual Java se puede expandir dinámicamente, se lanzará una excepción OutOfMemoryError cuando la pila se expanda y no se pueda solicitar suficiente memoria.

Pila de métodos nativos

La pila de métodos nativos sirve al método nativo utilizado por la máquina virtual. Su función es similar a la pila de la máquina virtual Java. Por supuesto, la pila del método local también arrojará excepciones StackOverflowError y OutOfMemoryError respectivamente cuando la profundidad de la pila se desborde o la expansión de la pila falle.

Montón de Java

El montón de Java es un área de memoria compartida por todos los subprocesos y se crea cuando se inicia la máquina virtual. El único propósito de esta área de memoria es almacenar instancias de objetos, y "casi" todas las instancias de objetos en el mundo Java asignan memoria aquí. Por supuesto, a medida que se desarrolla la tecnología, las instancias de objetos también pueden distribuirse en otros lugares.

El propósito de subdividir el montón de Java es simplemente recuperar mejor memoria o asignar memoria más rápido.

El montón de Java puede estar en un espacio de memoria físicamente discontinuo, pero lógicamente debería considerarse continuo. Pero para objetos grandes (típicamente objetos de matriz), es probable que la mayoría de las implementaciones de máquinas virtuales requieran espacio de memoria contiguo en aras de una implementación simple y una alta eficiencia de almacenamiento.

Si no hay memoria en el montón de Java para completar la asignación de la instancia y el montón ya no se puede expandir, la máquina virtual Java generará una excepción OutOfMemoryError.

montón

La imagen de arriba muestra la estructura en el montón de Java.

Sobre el principio de asignación de objetos en el montón:

Los objetos se asignan primero en el área del Edén

Los objetos grandes entran directamente en la vejez

Los objetos longevos entrarán en la vejez.

Área de métodos

El área de métodos, como el montón de Java, es un área de memoria compartida por cada hilo. Se utiliza para almacenar datos como información de tipo, constantes, variables estáticas y caché de código compilado por el compilador JIT que ha sido cargado por la máquina virtual.

HotSpot de JDK 7 ha eliminado el grupo de constantes de cadena y las variables estáticas que originalmente se colocaron en la generación permanente, pero en JDK 8, el concepto de generación permanente finalmente se abandonó por completo y se implementó en la memoria local como JRockit y J9. En cambio, Metaspace movió todo el contenido restante (principalmente información de tipo) de la generación permanente en JDK 7 al metaespacio.

Tenga en cuenta que en el párrafo anterior, JDK8 no tiene generación permanente, pero usa metaspace. En JDK7, a muchas personas les gustaba confundir el área de método con la generación permanente.

El comportamiento de recolección de basura es relativamente raro en esta área, pero no es que los datos ingresen al área del método como "permanente" como el nombre de la generación permanente. El objetivo de recuperación de memoria de esta área es principalmente para la recuperación del pool constante y la descarga de tipos. Si el área de método no puede cumplir con los nuevos requisitos de asignación de memoria, se lanzará una excepción OutOfMemoryError.

Grupo constante de tiempo de ejecución

El grupo de constantes de tiempo de ejecución es parte del área de métodos. Además de la información de descripción de la versión de la clase, campos, métodos, interfaces, etc. en el archivo de la clase, también hay una tabla de pool constante (Constant Pool Table), que se utiliza para almacenar varias referencias literales y simbólicas generadas durante la compilación. Esta parte El contenido se almacenará en el grupo de constantes de tiempo de ejecución en el área de método después de que se cargue la clase.

El grupo de constantes de tiempo de ejecución es parte del área de métodos. Cuando el grupo de constantes ya no pueda solicitar memoria, se lanzará un OutOfMemoryError.

Memoria directa

La memoria directa (Direct Memory) no forma parte del área de datos de la máquina virtual cuando se está ejecutando, pero esta parte de la memoria también se usa con frecuencia y también puede causar OutOfMemoryError.

Objeto

En la máquina virtual HotSpot, el diseño de almacenamiento de los objetos en la memoria dinámica se puede dividir en tres partes: encabezado del objeto (encabezado), datos de instancia (datos de instancia) y relleno de alineación (relleno).

La parte del encabezado del objeto del objeto de la máquina virtual HotSpot incluye dos tipos de información. El primer tipo se utiliza para almacenar los datos en tiempo de ejecución del propio objeto, también llamado "Marcar palabra". La información de "Marcar palabra" es la siguiente:

Marcar palabra

Nuestro programa Java manipulará los objetos específicos en el montón a través de los datos de referencia en la pila. Los métodos de acceso convencionales utilizan principalmente el identificador y el puntero directo.

  • Acceso de identificador: una parte de la memoria se puede dividir en el montón de Java como grupo de identificadores. La dirección del identificador del objeto se almacena en la referencia y el identificador contiene la información de dirección específica de los datos de instancia del objeto y los datos de tipo.

  • Acceso directo al puntero: el diseño de memoria del objeto en el montón de Java debe considerar cómo colocar la información relacionada con los datos del tipo de acceso. La referencia almacenada en el objeto es directamente la dirección del objeto. Si solo accede al objeto en sí, no hay necesidad de una sobrecarga de acceso indirecto adicional

Generalmente, la máquina virtual HotSpot usa el segundo acceso de puntero directo.

Puntero directo

Aquí hago una pregunta para que todos piensen:

¿Cómo escribir código para la excepción de desbordamiento de pila y la excepción de desbordamiento de pila?

Esta es una pregunta frecuente durante las entrevistas. Con respecto a las excepciones de desbordamiento de pila, puede pensar en crear objetos para que puedan romper la memoria de pila; con respecto a las excepciones de desbordamiento de pila, puede pensar en cómo llenar la pila con marcos de pila.

Recomendado en el pasado

Escanee el código QR para ser más emocionante. O busque Lvshen_9 en WeChat , puede responder para obtener información en segundo plano

1.回复"java" 获取java电子书;

2.回复"python"获取python电子书;

3.回复"算法"获取算法电子书;

4.回复"大数据"获取大数据电子书;

5.回复"spring"获取SpringBoot的学习视频。

6.回复"面试"获取一线大厂面试资料

7.回复"进阶之路"获取Java进阶之路的思维导图

8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)

9.回复"总结"获取Java后端面试经验总结PDF版

10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)

11.回复"并发导图"获取Java并发编程思维导图(xmind终极版)

Otro: haga clic en [ Mis beneficios ] para tener más sorpresas.

Supongo que te gusta

Origin blog.csdn.net/wujialv/article/details/109173690
Recomendado
Clasificación