Introducción a la estructura de memoria JVM

67f50442ac9d49ac8a1073e10c80471c.jpg1. Proceso de compilación y ejecución de código Java

 

  1. Compilación del código fuente: compile el código Java en el código de bytes JVM (archivo .class) a través del compilador de código fuente Java

 

  2. Carga de clases: la carga de clases de la JVM se completa a través de ClassLoader y sus subclases.

 

  3. Ejecución de clase: el código de bytes se carga en la memoria, ingresa a la máquina virtual JVM y es interpretado y ejecutado por el intérprete

 

 

 

   Nota: La plataforma Java está construida por la máquina virtual Java y la interfaz del programa de aplicación Java, y el lenguaje Java es el canal para ingresar a la plataforma.

 

     Los programas escritos y compilados en el lenguaje Java pueden ejecutarse en esta plataforma

 

2. Introducción a JVM

1. Después de compilar el programa Java una vez, el código Java se compila en un código de bytes, es decir, un archivo de clase, y luego se interpreta en diferentes sistemas operativos basándose en diferentes máquinas virtuales Java y finalmente se convierte en códigos de máquina de diferentes plataformas. , y finalmente obtuve el implemento

 

2. La máquina virtual Java (JVM) está en el centro, que es la clave de que el programa no tiene nada que ver con el sistema operativo y el hardware subyacentes.

 

   Debajo de la JVM se encuentra la interfaz de portabilidad. La interfaz de portabilidad consta de dos partes: el adaptador y el sistema operativo Java. La parte que depende de la plataforma se denomina adaptador. La JVM se implementa en la plataforma y el sistema operativo específicos a través de la portabilidad. interfaz.

 

   Por encima de la JVM se encuentran la biblioteca de clases básica y la biblioteca de clases extendidas de Java y sus API. Las aplicaciones y los pequeños programas (applets de Java) escritos con las API de Java pueden ejecutarse en cualquier plataforma Java, independientemente de la plataforma subyacente.

 

   La máquina virtual de Java (JVM) realiza la separación del programa y el sistema operativo, realizando así la multiplataforma de Java.

 

        

 

3. La JVM tiene una tarea clara en su ciclo de vida que es ejecutar el programa Java, por lo que cuando se inicia el programa Java se genera una instancia de la JVM, cuando el programa termina de ejecutarse la instancia también desaparece

 

4. Tres tipos de JVM: ① HotSpot de Sun Company ② JRockit de BEA Company ③ J9 JVM de IBM Company

 

   En JDK1.7 y anteriores, usamos el HotSpot de Sun, pero dado que tanto Sun como BEA fueron adquiridos por Oracle, jdk1.8 usará la esencia del HotSpot de Sun y JRockit de BEA para formar la JVM de jdk1.8.

 

3. Arquitectura JVM

  

 

  

 

1. Cargador de clases Cargador de clases

       Responsable de cargar archivos .class, los archivos de clase tienen una marca de archivo específica al principio del archivo, y ClassLoader es responsable de cargar archivos de clase, etc. En cuanto a si se puede ejecutar, lo determina el motor de ejecución.

  ① Localice e importe archivos de clase binarios

  ② Verificar la corrección de las clases importadas

  ③ Asignar memoria de inicialización para la clase

  ④ Ayuda a resolver referencias de símbolos.

2. Interfaz local de interfaz nativa

  El papel de la interfaz local es integrar diferentes lenguajes de programación para Java. Su intención original es integrar programas C/C++. Cuando C/C++ estaba desenfrenado cuando nació Java, si quieres afianzarte, debes llamar programas C/C++, por lo que en Se abre un área especial en la memoria para el procesamiento marcada como

  Código nativo, su método específico es registrar el método nativo en la pila de métodos nativos y cargar las bibliotecas nativas cuando se ejecuta el motor de ejecución.

  En la actualidad, este método se usa cada vez menos, excepto para aplicaciones relacionadas con el hardware, como controlar impresoras a través de programas Java o equipos de producción de gestión de sistemas Java, que es relativamente raro en las aplicaciones de nivel empresarial.

  Debido a que la comunicación entre campos heterogéneos está muy desarrollada ahora, por ejemplo, se puede usar la comunicación Socket y también se puede usar el Servicio web.

3. Motor de Ejecución Motor de Ejecución: Ejecuta las instrucciones envueltas en el método de carga de la clase, es decir, el método.

4.Área de datos de tiempo de ejecución área de datos de ejecución (es decir, memoria de máquina virtual o memoria JVM presentada en la siguiente sección)

      Abra una parte de la memoria de toda la memoria de la computadora para almacenar objetos, variables, etc. que JVM necesita usar, dividida en: área de método, montón, pila de máquina virtual, contador de programa y pila de método local.

Cuatro, estructura de memoria JVM

 

1. Registro de PC del contador de programa

 

  Cada subproceso tiene una calculadora de programa, que es un puntero al código de bytes del método en el área del método (el siguiente código de instrucción que se ejecutará), y el motor de ejecución lee la siguiente instrucción, que es un espacio de memoria muy pequeño, casi insignificante.

 

  El contador de programa (Registro de contador de programa) es un pequeño espacio de memoria, y su función puede considerarse como el indicador de número de línea del código de bytes ejecutado por el hilo actual. En el modelo conceptual de la máquina virtual (solo un modelo conceptual, varias máquinas virtuales pueden implementarse de alguna manera más eficiente), el intérprete de bytecode funciona cambiando el valor de este contador para seleccionar el siguiente a ejecutar Funciones básicas como las instrucciones de código de bytes, las bifurcaciones, los bucles, los saltos, el manejo de excepciones y la recuperación de subprocesos deben depender de este contador para completarse. Dado que los subprocesos múltiples de la máquina virtual Java se realizan cambiando los subprocesos a su vez y asignando el tiempo de ejecución del procesador, en un momento dado, un procesador (un núcleo para un procesador multinúcleo) solo ejecutará instrucciones de un subproceso en formato . Por lo tanto, para volver a la posición de ejecución correcta después del cambio de subproceso, cada subproceso debe tener un contador de programa independiente. Los contadores entre subprocesos no se afectan entre sí y se almacenan de forma independiente. Llamamos a este tipo de área de memoria "subproceso privado". . " memoria. Si el subproceso 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; si el subproceso está ejecutando un método Natvie, el valor del contador está vacío (sin definir). Esta región de memoria es la única que no especifica ninguna condición OutOfMemoryError en la especificación de máquina virtual de Java.

 

2. Pila de métodos nativos

 

  Registre el método nativo en la pila de métodos nativos y cargue las bibliotecas nativas cuando se ejecute el motor de ejecución.

 

  La pila de métodos locales es básicamente similar a la pila de máquinas virtuales, la diferencia es que la pila de máquinas virtuales sirve al método Java ejecutado por la máquina virtual, mientras que la pila de métodos locales sirve al método nativo.

 

3. Área de método

 

  Se utiliza para almacenar la carga de la máquina virtual: variables estáticas + constantes + información de clase + conjunto de constantes de tiempo de ejecución (información de clase: versión de clase, campo, método, interfaz, constructor y otra información de descripción)

 

  El valor mínimo predeterminado es 16 MB y el valor máximo es 64 MB. El tamaño del área del método puede estar limitado por los parámetros -XX:PermSize y -XX:MaxPermSize

 

  Para los desarrolladores que están acostumbrados a desarrollar e implementar programas en la máquina virtual HotSpot, muchas personas están dispuestas a llamar al área de métodos "Generación permanente" (Permanent Generation). Los dos no son equivalentes en esencia, solo porque la máquina virtual HotSpot El diseño El equipo optó por extender la colección generacional de GC al área de métodos, o usar la generación permanente para implementar el área de métodos. Para otras máquinas virtuales (como BEA JRockit, IBM J9, etc.), no existe el concepto de generación permanente. Incluso para la propia máquina virtual HotSpot, según la información oficial de la hoja de ruta, ahora existe un plan para abandonar la generación permanente y "mover" a Native Memory para implementar el área de métodos. La especificación de la máquina virtual de Java tiene restricciones muy flexibles en esta área.Además de no requerir memoria continua como el montón de Java y puede elegir un tamaño fijo o ampliable, también puede optar por no implementar la recolección de elementos no utilizados. En términos relativos, los comportamientos de recolección de basura rara vez ocurren en esta área, pero eso no significa que los datos ingresen al área de método y existan "permanentemente" como el nombre de la generación permanente. El objetivo del reciclaje de memoria en esta área es principalmente para el reciclaje de conjuntos constantes y la descarga de tipos. El reciclaje es realmente necesario. En la lista de BUG de Sun, han aparecido varios BUG graves porque la máquina virtual HotSpot de versión baja no recuperó completamente esta área, lo que provocó pérdidas de memoria. De acuerdo con la especificación de la máquina virtual de Java, cuando el área del método no puede cumplir con los requisitos de asignación de memoria, se generará una excepción OutOfMemoryError.

 

4. Apilar la pila JVM

 

  Varios tipos de datos básicos conocidos por el compilador (boolean, byte, char, short, int, float, long, double), referencia de objeto (puntero de referencia, no el objeto en sí)

 

  La pila es el modelo de memoria para la ejecución del método Java:

 

  Cuando se ejecuta cada método, se crea un "marco de pila" para almacenar la tabla de variables locales (incluidos los parámetros), la pila de operaciones, la salida del método y otra información.

 

  El proceso desde la llamada hasta la ejecución de cada método corresponde al proceso de un marco de pila desde que se inserta hasta que se extrae en la pila de la máquina virtual.

 

  (Tabla de variables locales: almacena varios tipos de datos básicos conocidos por el compilador (boolean, byte, char, short, int, float, long, double), referencia de objeto (puntero de referencia, no el objeto en sí),

 

  Entre ellos, los datos de tipo doble y largo de 64 bits ocuparán el espacio de 2 variables locales, y los otros tipos de datos solo ocuparán 1 espacio.

 

  El espacio de memoria requerido por la tabla de variables locales se asigna durante la compilación. Al ingresar un método, se determina completamente cuántas variables locales debe asignar este método en el marco de la pila. El marco de la pila no cambiará el tamaño de la tabla de variables locales durante la compilación. operación. espacio)

 

  El ciclo de vida de la pila sigue el ciclo de vida del subproceso. Se crea cuando se crea el subproceso, y la memoria de la pila se libera cuando finaliza el subproceso, que es privado para el subproceso.

 

5. Montón montón de Java

 

  Todas las instancias de objetos y matrices se asignan en el montón, y el único propósito de esta área de memoria es almacenar instancias de objetos.

 

  El montón es la porción más grande de memoria administrada por la máquina virtual Java. El montón de Java es un área de memoria compartida por todos los subprocesos, creada cuando se inicia la máquina virtual

 

  El montón es el área más importante para comprender el mecanismo Java GC, nadie

 

  Estructura: Generación Cenozoica (área Eden + 2 áreas Survivor) Generación permanente generación antigua (HotSpot has)

 

  Nueva generación: objetos de nueva creación --> Eden area 

 

  Después de GC, los objetos sobrevivientes ingresan al área de Supervivientes 1 desde el área de Supervivientes 0 en el área de Eden   

 

  GC nuevamente, los objetos sobrevivientes ingresan al área de Supervivientes 0 desde el área de Supervivientes 1 en el área de Eden 

 

  Generación anterior: si el objeto ha sobrevivido lo suficiente en la generación joven sin ser limpiado (es decir, ha sobrevivido a varios GC jóvenes), se copiará en la generación anterior.

 

  Si el objeto recién creado es relativamente grande (como una cadena larga o una matriz grande) y el espacio en la nueva generación es insuficiente, el objeto grande se asignará directamente a la generación anterior (los objetos grandes pueden desencadenar una GC temprana, por lo que debe usarse menos y deben evitarse los objetos grandes de corta duración.

 

  El espacio de la generación anterior es generalmente más grande que el de la nueva generación, que puede almacenar más objetos, y la cantidad de GC que se producen en la generación anterior es menor que la de la generación joven.

 

  Generación permanente: puede entenderse simplemente como un área de método (los dos no son equivalentes en esencia)

 

  Como se mencionó anteriormente: para los desarrolladores que están acostumbrados a desarrollar e implementar programas en la máquina virtual HotSpot, muchas personas están dispuestas a llamar al área de métodos "generación permanente", y los dos no son equivalentes en esencia.

 

  Es solo porque el equipo de diseño de la máquina virtual HotSpot eligió extender la colección generacional de GC al área de métodos, o usar la generación permanente para implementar el área de métodos.

 

  Para otras máquinas virtuales (como BEA JRockit, IBM J9, etc.), no existe el concepto de generación permanente

 

  Incluso para la propia máquina virtual HotSpot, según la información oficial de la hoja de ruta, ahora existe un plan para abandonar la generación permanente y "mover" a Native Memory para implementar el área de métodos.

 

  Jdk1.6 y anteriores: el grupo constante se asigna en la generación permanente

 

  Jdk1.7: Sí, pero poco a poco ha ido "pasando a la generación permanente"

 

  Jdk1.8 y posteriores: sin generación permanente (java.lang.OutOfMemoryError: espacio PermGen, este error no aparecerá en JDK1.8)

 

6. Memoria directa Memoria directa

 

  La memoria directa no es la memoria administrada por la JVM, se puede entender que la memoria directa es la memoria de la máquina distinta de la JVM, por ejemplo, si tiene 4G de memoria y la JVM ocupa 1G, los 3G restantes son memoria directa.

 

  Hay un método de asignación de memoria basado en canales (Channel) y búferes (Buffer) en JDK. La biblioteca de funciones nativa implementada por el lenguaje C se asigna en la memoria directa y DirectByteBuffer hace referencia a ella almacenada en el montón de JVM.

 

  Dado que la memoria directa está limitada por la memoria de la máquina, también puede ocurrir la excepción de OutOfMemoryError.

Supongo que te gusta

Origin blog.csdn.net/weixin_57763462/article/details/131927986
Recomendado
Clasificación