Más que solo entrevistas: explicación detallada de las preguntas de la entrevista de carga de clase jvm

preguntas de entrevista

Aprender con preguntas es lo más eficiente, en esta ocasión intentaremos responder a las siguientes preguntas:

¿Qué es la carga de clases?
¿Qué situaciones desencadenan la carga de clases?
Cuénteme sobre el proceso de carga de una clase de JVM. ¿
Cuándo se asignará la memoria para las variables?
¿Cuál es el mecanismo de carga de clases de la JVM?
¿Se puede romper el mecanismo de delegación parental? ¿Por qué?
La respuesta se encuentra al final del artículo. Si no tiene tiempo para leer el principio, puede pasar al final y leer la respuesta directamente.

Principios detallados Ciclo
de vida de la clase
Creo que todo el mundo está familiarizado con el ciclo de vida de una clase, de la siguiente manera:
inserte la descripción de la imagen aquí

Pero esto siempre se olvida después de la memorización, y la memorización después del olvido, al igual que Ma Hemei, ¿verdad?

De hecho, una vez que lo entiendas, básicamente nunca lo olvidarás.

Loading
Loading hace principalmente tres cosas:

Encuentre el archivo de clase (obtenga el flujo de bytes binario que define esta clase a través del nombre completo de la clase)
y colóquelo en el área de método (convierta la estructura de almacenamiento estática representada por este flujo de bytes en la estructura de datos de tiempo de ejecución del área de método)
para abrir una entrada (Generar un objeto java.lang.Class que represente esta clase como la entrada para acceder a estas estructuras de datos en el área de métodos) En términos
generales, este paso consiste en leer la clase en la memoria a través del cargador de clases. Cabe señalar que aunque el objeto se genera en el tercer paso, no está en el montón, sino en el área de métodos.

Conexión
Conexión se divide en tres pasos Generalmente, las entrevistas prefieren preguntar sobre la preparación.

Verificar
Como su nombre lo indica, verifique si la información contenida en el flujo de bytes del archivo Class cumple con los requisitos de la máquina virtual actual.

Preparación
En este paso, las variables estáticas y las constantes estáticas recibirán memoria y valores asignados.

Cabe señalar que las variables estáticas solo recibirán valores predeterminados. Por ejemplo lo siguiente:

public static int value = 123;
Copiar
El valor asignado a value en este momento es 0, no 123.

Las constantes estáticas (modificadas por estáticas finales) se asignarán directamente. Por ejemplo lo siguiente:

public static final int value = 123;
Copiar
El valor asignado a value en este momento es 123.

Análisis
La fase de análisis es cuando jvm reemplaza la referencia simbólica del conjunto de constantes con una referencia directa.

Bueno... ¿qué es un grupo constante? ¿Qué es una referencia simbólica? ¿Qué es una cotización directa?

Ponemos el grupo constante en la estructura de memoria jvm. Permítanme hablar primero de lo que es una referencia simbólica y una referencia directa.

Referencias simbólicas y referencias directas
Supongamos que hay una clase Worker que contiene un método run() de clase Car, de la siguiente manera:

class Worker{ ... public void gotoWork(){ car.run(); //La representación binaria de este código en la clase Worker es una referencia simbólica} ...}
Copiar
Antes de la fase de análisis, la clase Worker no know car.run() ¿Dónde está la memoria de este método, por lo que solo se puede usar una cadena para representar este método? La cadena contiene suficiente información, como información de clase, nombre de método, parámetros de método, etc., para que se pueda encontrar la ubicación correspondiente para su uso real.

Esta cadena se denomina referencia de símbolo.

En la etapa de análisis, jvm encuentra la dirección correspondiente en el área de la memoria de acuerdo con el contenido de la cadena y luego reemplaza la referencia simbólica con un puntero, identificador, desplazamiento, etc. que apuntan directamente al objetivo, y luego puede ser utilizado directamente.

Estos punteros, controladores y desplazamientos que apuntan directamente al destino se denominan referencias directas.

Inicialización
La tarea principal de la inicialización de la clase es asignar el valor inicial establecido por el programa a la variable estática.

Recuerde la variable estática anterior:

public static int value = 123;
Copiar
Después de este paso, el valor de value es finalmente 123.

El resumen es el siguiente:
inserte la descripción de la imagen aquí

Las condiciones para la inicialización de clases
La especificación de máquina virtual de Java estipula estrictamente que solo hay cinco situaciones en las que se debe inicializar una clase:

Use la nueva instrucción de código de bytes para crear una instancia de una clase, o use getstatic, putstatic para leer o establecer el valor de un campo estático (excepto para las constantes colocadas en el grupo de constantes), o cuando llame a un método estático, la clase correspondiente debe ser inicializado.
Al usar el método del paquete java.lang.reflect para realizar una llamada reflexiva a la clase, si la clase no se ha inicializado, debe inicializarse primero.
Al inicializar una clase, si se descubre que su clase principal no se ha inicializado, primero se activa la inicialización de la clase principal.
Cuando se inicia la máquina virtual, el usuario debe especificar una clase principal (la clase que contiene el método main()), y la máquina virtual primero inicializa esta clase.
Al usar el soporte de lenguaje dinámico de jdk1.7, si el resultado final del análisis de una instancia java.lang.invoke.MethodHandle es el identificador de método de REF_getStatic, REF_putStatic, RE_invokeStatic y la clase correspondiente a este identificador de método no se ha inicializado, primero debe desencadenar su inicialización.
Además de los cinco casos anteriores, ningún otro caso activará la inicialización de la clase.

Por ejemplo, las siguientes situaciones no desencadenarán la inicialización de clases:

Llame a los campos estáticos de la clase principal a través de la subclase. En este momento, la clase principal cumple la condición 1, mientras que la subclase no cumple ninguna condición. Entonces solo se inicializa la clase principal.
Hacer referencia a una clase a través de una matriz no activa la inicialización de la clase. Porque new es una matriz, no una clase.
La constante estática de la clase que llama no activará la inicialización de la clase, porque la constante estática se almacenará en el grupo de constantes de la clase que llama durante la fase de compilación y no se referirá a la clase que define la constante.
Mecanismo de carga de clases
Cargador de
clases Como dijimos anteriormente, la fase de carga necesita "obtener un flujo de bytes binarios que describa esta clase a través del nombre completo de una clase". Esto es lo que está haciendo el cargador de clases.

El jvm viene con tres cargadores de clases, a saber:

Inicie el cargador de clases.
Cargador de clases de extensión.
Cargador de clases de aplicación
Su relación de herencia es la siguiente:
inserte la descripción de la imagen aquí

Delegación de padres
El proceso de funcionamiento del mecanismo de delegación de padres es el siguiente:

El ClassLoader actual primero consulta si esta clase se ha cargado desde sus clases ya cargadas y, si ya se ha cargado, devuelve directamente la clase cargada originalmente. Cada cargador de clases tiene su propio caché de carga. Cuando se carga una clase, se colocará en el caché y se puede devolver directamente cuando se cargue la próxima vez.
Cuando la clase cargada no se encuentra en el caché del cargador de clases actual, se le confía al cargador de clases principal que la cargue. El cargador de clases principal adopta la misma estrategia, primero verifica su propio caché y luego confía la clase principal de la clase principal. para cargar hasta bootstrp ClassLoader.Cuando
todos los cargadores de clases principales no están cargados, el cargador de clases actual lo cargará y lo colocará en su propio caché, de modo que regresará directamente cuando haya una solicitud de carga la próxima vez.
¿Por qué es tan complicado? ¿No puedes manejarlo tú solo?

Las ventajas de la delegación parental son las siguientes:

Evite la doble carga. Cuando el padre ya ha cargado la clase, no es necesario que el ClassLoader hijo la vuelva a cargar.
por seguridad. Evite el reemplazo de clases principales como String.
Romper la delegación de los padres
El mecanismo de "delegación de los padres" es solo un mecanismo recomendado por Java, no un mecanismo obligatorio.

Por ejemplo, JDBC rompe el mecanismo de delegación de padres. Obtiene el cargador de contexto del subproceso a través de Thread.currentThread().getContextClassLoader() para cargar la clase de implementación del controlador, rompiendo así el mecanismo de delegación principal.

En cuanto a por qué, hablaré de ello más adelante.

Respuesta
Ahora, podemos responder a la pregunta planteada al principio del artículo. Trate de responder sobre la base de la comprensión, sin memorización.

¿Qué es la carga de clases?
Después de que la JVM obtiene el flujo binario de la clase a través del nombre de la clase, el proceso de colocar la clase en el área de método y crear el objeto de entrada se denomina carga de clase. Después de cargar, la clase se coloca en la memoria.
¿Qué situaciones desencadenan la inicialización de una clase?
Las clases se inicializarán en 5 casos:
Primero, si esta clase es una clase de entrada, se inicializará.
Segundo, use new para crear objetos, o llame a variables estáticas de la clase, y la clase se inicializará. Pero las constantes estáticas no cuentan.
En tercer lugar, obtenga la clase a través de la reflexión y la clase se inicializará.
En cuarto lugar, si se inicializa la subclase, también se inicializará su clase principal.
En quinto lugar, al usar el soporte de lenguaje dinámico de jdk1.7, la llamada al identificador estático también se inicializará.
Hábleme sobre el proceso de JVM cargando una clase
Igual que la pregunta 1. Pero aquí también puedes preguntarle al entrevistador si quiere preguntar sobre el ciclo de vida de la clase. Si está preguntando sobre el ciclo de vida de una clase, puede responder que hay cinco etapas de "carga, conexión, inicialización, uso y descarga", y la conexión se puede dividir en tres etapas de "verificación, preparación y análisis".
¿Cuándo se asignará la memoria para las variables?
Asigne memoria para variables estáticas durante la fase de preparación.
¿Cuál es el mecanismo de carga de clases de la JVM?
El mecanismo de delegación principal, el cargador de clases primero permitirá que se cargue su clase principal, y si la clase principal no se puede cargar, la cargará por sí mismo.
¿Se puede romper el mecanismo de delegación parental? ¿Por qué
puede romperse, como JDBC rompe el mecanismo de delegación principal utilizando el cargador de contexto de subprocesos? La razón es que JDBC solo proporciona una interfaz, no una implementación. Esta pregunta se puede encontrar en la literatura citada.

Supongo que te gusta

Origin blog.csdn.net/m0_54861649/article/details/126628764
Recomendado
Clasificación