La Red de Conocimientos Pedagógicos - Currículum vitae - ¿Cómo funciona la máquina virtual Java?

¿Cómo funciona la máquina virtual Java?

Introduzca el principio de funcionamiento de la máquina virtual Java desde una perspectiva macro. Cómo ejecutar un archivo fuente de Java (archivo .java) desde cero, como se muestra en la figura siguiente, primero el compilador de front-end (javac o ECJ) compila el archivo fuente de Java en un archivo de código de bytes de Java y luego el JRE carga el Archivo de código de bytes de Java en El área de memoria asignada a la JVM por el sistema es luego interpretada o compilada por el motor de ejecución, y el compilador justo a tiempo convierte el código de bytes en código de máquina. Este artículo presenta principalmente el cargador de clases y el área de datos de tiempo de ejecución en la siguiente figura.

(1) La carga de clases se refiere a leer los datos binarios (.class) en el archivo de código de bytes en la memoria, en el área de método del área de datos en tiempo de ejecución y luego crear un archivo java. El objeto .Class encapsula la estructura de datos de la clase en el área de método. El producto final de la carga de clases es un objeto de clase ubicado en el montón, que encapsula la estructura de datos de la clase en el área de método y proporciona una interfaz para que el programa JAVA acceda a la estructura de datos en el área de método. A continuación se muestra un diagrama de jerarquía de cargadores de clases.

BootstrapClassLoader: Creado cuando la JVM se está ejecutando, es responsable de cargar los archivos de clase jre\lib almacenados en el directorio de instalación del JDK, o la biblioteca de clases en la ruta especificada por el parámetro -xbootclasspass, que puede ser reconocido por la máquina virtual (como rt.jar, todas las clases que comienzan con java.* son cargadas por el cargador de clases de arranque). Los programas JAVA no pueden hacer referencia directamente a la clase de inicio.

Cargador de clases extendido: este cargador de clases es responsable de cargar las clases \jre\lib\ext en el directorio de instalación de JDK, o todas las bibliotecas de clases en la ruta especificada por la variable de sistema java.ext.dirs. Los desarrolladores también pueden utilizar cargadores de clases de extensión directamente.

Cargador de clases de aplicaciones: Responsable de cargar las clases especificadas por la ruta de clases del usuario. Los desarrolladores pueden usar este cargador de clases directamente. Si la aplicación no define su propio cargador de clases, este cargador de clases es el cargador de clases predeterminado.

Cargador de clases personalizado: el cargador de clases que viene con la JVM carga archivos de clases Java estándar desde el sistema de archivos local. El cargador de clases personalizado puede verificar automáticamente las firmas digitales antes de ejecutar código que no es de confianza y crear dinámicamente clases construidas personalizadas satisfactorias. para necesidades específicas del usuario, obteniendo clases Java de lugares específicos (base de datos, red).

Tenga en cuenta que el cargador de clases anterior no se implementa mediante herencia, sino mediante composición. El modo de carga de la máquina virtual JAVA es el modo de delegación, como se muestra en los pasos 1 a 7 anteriores. El cargador de abajo puede ver las clases en el cargador de arriba, pero no al revés. El cargador de clases puede cargar clases pero no puede descargarlas. Habiendo dicho muchas cosas, todavía siento la necesidad de usar algún código para explicar las cosas.

Primero, defina su propio cargador de clases MyClassLoader, que hereda del cargador de clases y anula el método findClass(nombre de cadena) de la clase principal de la siguiente manera:

Use la definición Un buen MyClassLoader carga el archivo de código de bytes especificado, como cargar el archivo de código de bytes Test.class en C:\\Users\\Administrator\\. El código es el siguiente:

(2) Área de datos de tiempo de ejecución

El primer paso de carga del código de bytes, seguido de autenticación, preparación, análisis e inicialización, luego estos pasos se realizan específicamente. Las tareas se muestran en la siguiente figura:

(3) A continuación se presentará el área de datos de tiempo de ejecución, que se divide principalmente en área de método, montón de Java, pila de máquina virtual, pila de método local y contador de programa. Al igual que el montón de Java, el área de método es un área de memoria compartida por cada hilo, mientras que la pila de máquina virtual, la pila de método local y el contador de programa son áreas de memoria privada para cada hilo.

Montón de Java: el montón de Java es la mayor parte de la memoria administrada por la máquina virtual Java. Es compartida por todos los subprocesos del proceso y se crea cuando se inicia la máquina virtual. El único propósito de esta área es almacenar instancias de objetos, y casi todas las instancias de objetos asignan memoria aquí. Con el desarrollo de los compiladores JIT y la madurez gradual de la tecnología de rama de escape, las tecnologías de optimización como la asignación de pila y el reemplazo escalar hacen que la asignación de memoria en el montón ya no sea tan "absoluta". El montón de Java es el área principal administrada por el recolector de basura.

Debido a que el recopilador actual básicamente utiliza un algoritmo de recopilación generacional, el montón de Java también se puede dividir en era antigua y nueva generación (Eden, de sobreviviente a sobreviviente). Según la Especificación de la máquina virtual Java, el montón de Java puede estar en un espacio de memoria físicamente discontinuo siempre que sea lógicamente contiguo. El tamaño de esta área se puede ampliar con los parámetros -Xmx y -Xms. Si no hay memoria en el montón para completar la asignación de instancias y el montón no se puede expandir, se generará una excepción OutOfMemoryError.

Área de método: se utiliza para almacenar información de clases, constantes, variables estáticas, código compilado por el compilador justo a tiempo y otros datos cargados por la máquina virtual Java. A diferencia del montón de Java, la especificación de la máquina virtual Java tiene restricciones muy flexibles en el área del método y puede optar por no implementar la recolección de basura. Sin embargo, cuando los datos ingresan al área del método, no están allí "permanentemente". El objetivo del reciclaje de memoria en esta área es principalmente el reciclaje de pools constantes y la descarga de tipos. Si no hay suficiente memoria en esta área, se generará una excepción OutOfMemoryError.

Hengchi: Este término puede verse con frecuencia y forma parte del campo método. Además de describir la versión, campos, métodos, interfaces y otra información del archivo de clase, también hay un grupo constante que se utiliza para almacenar varias cantidades de texto y referencias de símbolos generados durante la compilación. Durante la ejecución de la máquina virtual Java, también se pueden colocar nuevas constantes en el grupo de constantes (como el método intern() de la clase String).

Pila de máquina virtual: Los subprocesos son privados y tienen el mismo ciclo de vida que los subprocesos. La pila de la máquina virtual describe el modelo de memoria de ejecución del método Java: cada método crea un marco de pila durante la ejecución para almacenar tablas de variables locales, pilas de operandos, enlaces dinámicos, salidas de métodos 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 a otro en la pila de la máquina virtual. Si la profundidad de la estación solicitada es mayor que la profundidad permitida por la máquina virtual, se generará una excepción StackOverflowError. Si la pila de la máquina virtual no puede solicitar suficiente memoria durante la expansión dinámica, se generará una excepción OutOfMemoryError.

Explica los cambios en cada parte del área de datos cuando el programa se ejecuta mediante el código más simple.

(4) Compile el archivo Test.java en Test.class a través del compilador y use javap -verbose Test.class para analizar el código de bytes compilado, como se muestra en la siguiente figura:

(5) Verifique los cambios en el área de datos durante el tiempo de ejecución: