Lo que JVM necesita cargar es una secuencia binaria, que puede ser en forma de un archivo .class u otros formularios. Si lo diseña de acuerdo con los estándares de carga, no habrá un gran problema.
Lo siguiente analiza principalmente los dos problemas de mecanismo y estándares:
Primero, tomemos el mecanismo de carga de los archivos de clase Java, que es similar al mecanismo de carga de las variables. Primero carga el archivo de clase en la memoria, luego verifica, analiza e inicializa los datos, y finalmente forma un tipo Java que la máquina virtual puede usar directamente. Dado que Java adopta el mecanismo JIT, será lento para cargarse, pero sus ventajas son obvias, tiene una alta flexibilidad y admite una carga dinámica y conexiones dinámicas.
A continuación, hablemos sobre el proceso de carga de la clase:
El proceso básico de carga de clase está en el siguiente orden, pero algunos no están estrictamente en este orden, y algunos están en el orden desordenado. Por ejemplo, la carga dinámica requiere inicialización y luego análisis.
1. Carga
Depende de la máquina virtual decidir, pero también hay casos en los que se ejecuta la fase anterior porque se ejecuta la siguiente fase.
En este momento, la máquina virtual hace tres cosas:
Primero, lea la secuencia binaria del archivo a través de un nombre totalmente calificado;
Segundo, coloque los métodos y variables estáticas en el archivo en el área del método;
Tercero, genere un objeto y póngalo en el montón como un portal de acceso.
Tenga en cuenta que el primero es leer la transmisión binaria, y no dice de qué archivo se lee o de dónde se lee. Por lo tanto, crea una fuerte escalabilidad en Java, que puede ser de jar, zip o de la capa de red, capa de base de datos, etc.
Principalmente la declaración de objeto y área de método.
2. Verificación
Asegúrese de que el flujo binario cumpla con los requisitos de la máquina virtual y no cumpla con VerifyError.
Primero, la verificación del formato de archivo, si hay números mágicos y si cumplen con los requisitos de los archivos Java;
En segundo lugar, la verificación de metadatos, si cumple con las especificaciones del código Java, como si la clase abstracta está directamente instanciada, si la clase ordinaria tiene objeto de clase principal indirecta o directa, etc.; En tercer lugar, la verificación de Bytecode, analiza el flujo de datos y el flujo de control, y asegura que no habrá comportamiento que dañe la máquina virtual, como si llamar a instrucciones inexistentes, ya sea asignar la clase principal a la subclase, si asigna el objeto a un objeto de este tipo, etc.;
Cuarto, verificación de referencia simbólica, principalmente si se puede encontrar la descripción de clases, variables y método, como si el archivo se puede encontrar con un nombre totalmente calificado, si es accesible, etc.
Determinar principalmente la estructura interna
3. Preparar
Asignar un valor inicial a una variable de clase suele ser un valor 0, como una variable estática, sin asignar un valor a una variable de instancia.
4. Análisis
El proceso de convertir referencias simbólicas en un grupo constante en referencias directas. La referencia simbólica mencionada aquí se refiere al tipo de variable, y la referencia directa se refiere al mango que puede ubicarse directamente al objeto. Clase, método, campo, análisis de interfaz, obtenga el objeto relevante de acuerdo con el nombre totalmente calificado y obtenga su tipo. Si no hay acceso a la clase, se arrojará ilegalAccesserRor, no se lanzará ningún campo Nosuchfielderror, no se lanzará ningún método NosuchmethodeRor, si es una clase o no, la interfaz se lanzará.
5. Inicialización
Cargue las clases y los recursos necesarios de acuerdo con los requisitos del programa. Solo hay cuatro situaciones, y debe inicializarse activamente antes de poder realizar la próxima operación, por lo que primero debe realizar los cuatro pasos anteriores.
Primero, las clases con palabras clave nuevas o estáticas, los nuevos objetos y las cargas estáticas estáticas, estas dos obviamente se inicializarán;
En segundo lugar, si usa una clase, no hay nada que pueda hacer al respecto;
Tercero, los métodos en la clase de reflexión deben inicializarse, ¿verdad?
Cuarto, la clase principal de ejecución, la clase que utiliza el método principal. No es necesario considerar otras situaciones de inicialización pasiva.
Pequeños ejemplos:
Public Class SuperClass {static {System.out.println ("SuperClass !!");} public static int value = 1;} Public Class Subclass extiende SuperClass {static {System.out.println ("Subclass!");}} Clase pública TestClassLoadload {public static ooid main (string [] args) Args) {System.out.println (subclass.value); superclass superclass = new subclass ();}} superclase !! 1subclass!El resultado de la ejecución muestra un problema: cuando la subclase llama a la variable de clase principal, la subclase no se inicializa porque la relación de código en este momento no tiene nada que ver con la subclase; Cuando se inicializa la subclase, la clase principal no se inicializa nuevamente porque la clase principal se ha inicializado en el cuerpo del método actual. La única diferencia entre una interfaz y una clase principal es que la inicialización de la interfaz no requiere la interfaz principal, y se inicializará solo cuando se use la interfaz principal, y se generará el mismo constructor de clase.
En este momento, el constructor de clase se cargará y se inicializarán todas las variables en la clase. Por supuesto, la clase principal se inicializará antes de la clase de niños.
6. Use
Después de cargar, cómo llamarlo, dibujar, cálculo, etc.
7. Desinstalar
La clase ya no se llama
Si las dos clases son iguales principalmente depende de la primera carga utilizando el mismo cargador, y la segunda dirección de nombre totalmente calificada es la misma
¿Por qué hacer las preguntas anteriores? A continuación, hablaremos sobre un mecanismo de carga de una máquina virtual.
Desde la perspectiva de las máquinas virtuales Java, hay dos cargadores de clase, uno se llama el cargador del sistema (bootstrap classloader), y el otro se llama cargador personalizado (extiende classloader). Esto se divide en dos, uno se llama cargador de aplicaciones y el otro se llama cargador de clase de extensión, que generalmente está predeterminado al primero; y la carga de nuestra aplicación se realiza principalmente por los tres cargadores anteriores. La relación entre los tres es Aplicación> Extensión> Bootsrap. El mecanismo de delegación matriz se refiere a la combinación de dos pares. El cargador infantil primero llama al método del cargador principal, y el objeto objetivo no se encuentra antes de usar el cargador infantil.
El pseudo-código es el siguiente:
LoadClass (Nombre de cadena, Boolean Resolve) {clase c = findloadedClass () if (c == null) {if (parent! = null) c = parent.loadclass (name, false); c = findbootstrapClassOrnull (name);} Catch (classnotfoundException e) {} if (c == null) c = findclass (name);}Java aboga por que escribamos la lógica de nuestra clase de llamadas en FindClass, lo que nos ayudará a usar el mecanismo de delegación matriz normalmente.
Destruir 1. Reescribir la Clase de carga
Destruir 2. Use el cargador de contexto de subproceso para dejar que el cargador principal llame al método del cargador infantil
Destrucción 3. El método de uso común para la carga en caliente es personalizar el cargador de clase y sobrescribir el módulo de errores original - OSGI
Sin embargo, si las reglas entre los cargadores personalizados están confundidos y hay un problema de referirse entre sí al mismo tiempo, la clase eventualmente no se encontrará, y se producirán fugas de mudanza y fugas de memoria.
Con respecto a la reparación en caliente, también conocido como complementos, los más populares son Hotfix, Nuwa, DroidFix y Fix, etc. Estos marcos se pueden encontrar en GitHub o en otro lugar. Los principios son como anteriores, los métodos son diversos, hay cobertura, redirección, etc., a través de la configuración, la configuración de acciones, etc.; Como complementos, se deben cumplir las siguientes condiciones:
1. Se puede instalar de forma independiente, pero no se puede ejecutar de forma independiente
2. Esté hacia atrás la compatibilidad, se puede ampliar
3. Solo puede ejecutarse en el programa host y puede deshabilitarse o reemplazarse
La explicación de ejemplo anterior del mecanismo de carga de máquina virtual avanzada Java es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.