Carga de clases [Java] y creación de objetos en Java

Mecanismo de carga de clases JAVA

La carga de clases de Java se divide en 5 procesos, a saber: carga, conexión (verificación, preparación, análisis), inicialización, uso y descarga.

  1. Cargando
    Cargando es principalmente para leer archivos .class (o paquetes zip) en la JVM a través de un flujo de bytes binarios. En la fase de carga, la JVM necesita completar 3 cosas:
    1) Obtener el archivo XXX.class de la ruta de clases a través del cargador de clases y leerlo en la memoria en forma de flujo binario.
    2) Convierta la estructura de almacenamiento estática representada por el flujo de bytes en la estructura de datos en tiempo de ejecución del área de métodos;
    3) Genere un objeto java.lang.Class de esta clase en la memoria para acceder a varios datos de esta clase en el área de métodos Entrada.

2.1 Verificación
Principalmente para asegurar que el flujo de bytes cargado cumple con la especificación JVM. La fase de verificación completará las siguientes 4 fases de acciones de inspección:
1) Verificación del formato de archivo
2) Verificación de metadatos (si cumple con la especificación del lenguaje Java)
3) Verificación de código de bytes (determinar que la semántica del programa es legal y lógica)
4) Verificación de referencia de símbolo ( (Asegúrese de que el siguiente análisis se pueda ejecutar normalmente)
2.2 Preparación La
preparación es el segundo paso de la fase de conexión, que principalmente asigna memoria para las variables estáticas en el área de método y establece el valor inicial predeterminado.
2.3 Resolución La
resolución es el tercer paso de la fase de conexión, que es el proceso en el que la máquina virtual reemplaza las referencias de símbolos en el grupo constante con referencias directas.

  1. Inicialización La
    fase de inicialización es el último paso del proceso de carga de clases, que consiste principalmente en asignar valores de forma activa a las variables de clase de acuerdo con las instrucciones de asignación en el programa.
    Cuando hay una relación de herencia, primero se inicializa la clase principal y luego se inicializa la clase secundaria, por lo que cuando se crea una clase secundaria, en realidad hay dos instancias de objeto en la memoria.
    Nota: Si la relación de herencia de la clase es demasiado larga, considerando solo la inicialización de la clase, este diseño no es preferible. Creo que has adivinado la razón.
    En general, se recomienda que la relación de herencia de clases no supere tres niveles como máximo, a saber, padre-hijo-nieto. En algunos escenarios de aplicaciones especiales, se puede agregar la capa 4, pero deténgase allí, la capa 4 ya tiene fallas de diseño de código.
  2. Utilice
    llamadas mutuas entre programas.
  3. Descargar
    significa destruir un objeto, lo que generalmente lo hace el recolector de basura JVM. La destrucción a nivel de código simplemente establece la referencia en nula.

Después de pasar la introducción general anterior, veamos el análisis de ejecución de Singleton2.getInstance ():
1) Carga de clases. Ejecute Singleton2.getInstance (), JVM no encontró la información relacionada de la clase Singleton por primera vez. Entonces, el archivo Singleton.class se carga en la memoria a través del cargador de clases.
2) Verificación de clase.
3) Se omite la preparación para la clase. Convierta los recursos estáticos en Singleton2 en el área de métodos. Value1, value2 y singleton se declaran inicialmente como 0, 0 y nulo en el área de métodos.
4) Análisis de clases. Omitir (el proceso de reemplazar las referencias de símbolo en el grupo constante con referencias directas)
5) Inicialización de la clase. Realice la asignación de propiedades estáticas. Valor de primer orden1 = 5, valor2 = 3, seguido de Singleton2 estático privado singleton2 = new Singleton2 ( );
esta operación es para crear objetos, de acuerdo con las conclusiones 1 antes de realizar el constructor Singleton2, ir a realizar recursos de recursos estáticos y no estáticos . Pero dado que value1 y value2 se han inicializado, la siguiente ejecución es el recurso no estático y, finalmente, el método de construcción de Singleton2: value1 ++; value2 ++.
Entonces Singleton2 da como resultado 6 y 4.

Además de aclarar el orden de ejecución, hay otro punto importante -> Conclusión 2: Los recursos estáticos solo se ejecutarán una vez en la inicialización de la clase . No confundir con el tercer paso.

Con la conclusión anterior, veamos el análisis de ejecución de Singleton.getInstance ():
1) Carga de clases. Cargue la clase Singleton en la memoria.
2) Verificación de clase.
3) Se omite la preparación para la clase. Convierta los recursos estáticos de Singleton2 en el área de método.
4) Análisis de clases. Omitir (el proceso de reemplazar las referencias de símbolo en el grupo constante con referencias directas)
5) Inicialización de la clase. Realice la asignación de propiedades estáticas. Singleton estático privado de primer orden singleton = new Singleton ( ), según las conclusiones 1 y las conclusiones 2 no realiza la asignación de esta operación de capa, valor1 y valor2. Por lo tanto, value1 y value2 en el objeto singleton son solo operaciones ++ basadas en 0. En este momento, value1 = 1 y value2 = 1 en el objeto singleton.
Entonces, public static int value1 = 5; public static int value2 = 3; Estas dos líneas de código realmente realizan la operación de asignación. Entonces el resultado final: 5 y 3.
Si la implementación es public static int value1; public static int value2; ¿cuál será el resultado? Resultado: 1 y 1.

Nota: ¿Por qué Singleton singleton = new Singleton () no asigna valor1, valor2? Porque la asignación de variables estáticas solo se realiza una vez en la inicialización de la clase.
Cuando el programa ejecuta Singleton estático privado singleton = new Singleton (), ya está asignando valores a las variables estáticas de la clase Singleton. Aquí new Singleton () es una asignación especial, similar a la capa interna recursiva, la capa externa ya es una operación de asignación, por lo que la capa interna filtrará automáticamente la operación de asignación de variables estáticas. Pero se seguirán asignando variables no estáticas.

Conclusión 3: Sobre la base de la conclusión 2, los recursos no estáticos se inicializarán con la creación del objeto. Cada vez que se crea un objeto, se realiza una inicialización.

Las conclusiones de dominio 1, 2 y 3 están básicamente familiarizadas con el orden de ejecución del programa en las clases de Java. Esto no es suficiente, ClassLoader aún no se ha introducido.

Cargador de clases

JVM proporciona los siguientes tres cargadores de clases de sistema:

  • Bootstrap ClassLoader : el cargador de clases de nivel superior es responsable de cargar el directorio JAVA_HOME \ lib o en la ruta especificada por el parámetro -Xbootclasspath, y es reconocido por la máquina virtual (identificado por el nombre del archivo, como rt.jar )el tipo.
  • Extension ClassLoader : Responsable de cargar la biblioteca de clases en el directorio JAVA_HOME \ lib \ ext o en la ruta especificada por la variable de sistema java.ext.dirs.
  • Cargador de clases de aplicación : también llamado cargador de clases del sistema, se puede obtener a través de getSystemClassLoader () y es responsable de cargar la biblioteca de clases en la ruta del usuario (classpath). Si no hay un cargador de clases personalizado, este suele ser el cargador de clases predeterminado.

Creación de objetos:

img

Descargo de responsabilidad: esta publicación de blog es una nota de estudio y se refiere a algunos recursos de la red. Si hay alguna infracción, háganoslo saber mediante un mensaje privado.

Supongo que te gusta

Origin blog.csdn.net/qq_42380734/article/details/105397532
Recomendado
Clasificación