1. Un comando corresponde a un proceso.
Cuando iniciamos un programa Java, es decir, cuando iniciamos un método principal, se iniciará un proceso de máquina virtual Java, sin importar cuán complejo sea el proceso. Los diferentes procesos JVM no se afectarán entre sí. Por eso se dice que el programa Java tiene una sola entrada: el método principal, que es llamado por la máquina virtual. Los dos métodos principales corresponden a dos procesos JVM, que inician dos cargadores de clases diferentes y, de hecho, operan clases diferentes. Por lo tanto no se afectarán entre sí.
2. Carga de clases.
Cuando usamos una clase, si la clase no se ha cargado en la memoria, el sistema inicializará la clase mediante carga, conexión e inicialización.
1. Carga de clases: se refiere a leer el archivo de clase de la clase en la JVM y crear un objeto Clase para él.
2. Conexión de clase: se refiere a fusionar los datos binarios de la clase en el JRE, que se divide en tres etapas:
a) Verificación: verifique la exactitud de los datos del archivo de clase cargado.
b). Preparación: asigne espacio de almacenamiento a las variables estáticas de la clase y realice la inicialización predeterminada.
c). Análisis: Reemplace las referencias de símbolos en los datos binarios de la clase con referencias directas.
3. Inicialización: inicializa las variables estáticas y los bloques de inicialización estáticos de la clase.
(Nota: para una propiedad estática de tipo final, si el valor de la propiedad se obtuvo en el momento de la compilación, llamar a la propiedad no hará que la clase se inicialice, porque esto equivale a usar una constante;
El uso del método ClassLoader() solo carga la clase y no la inicializa. )
3. Cargador de clases.
El cargador de clases es responsable de cargar archivos .class en la memoria y generar los objetos java.lang.Class correspondientes. Una vez que una clase se carga en la JVM, no se cargará nuevamente.
En Java, una clase se identifica por su nombre de clase completo (es decir, nombre de paquete + nombre de clase).
En la JVM, una clase se identifica por su nombre de clase completo y su cargador de clases.
Cuando la JVM se está ejecutando, se generarán tres ClassLoaders, a saber: BootstrapClassLoader (cargador de clases raíz), ExtClassLoader (cargador de clases extendido) y AppClassLoader (cargador de clases del sistema). La estructura UML es la siguiente:
Entre ellos, BootstrapClassLoader es responsable de cargar la biblioteca de clases principal de JRE. No es una subclase de ClassLoader y está escrito en C ++, por lo que no podemos verlo en Java. Cuando se obtiene a través del método getParent () de su subclase, será nulo. ser devuelto. BootstrapClassLoader es responsable de cargar las bibliotecas de clases principales de Java, como rt.jar y charsets.jar, en el destino JRE.
Como puede verse en la figura, ExtClassLoader y AppClassLoader son subclases de ClassLoader. No puedes verlos en la API, están en el archivo rt.jar. Los nombres de clase completos son:
sun.misc.Launcher$ExtClassLoader y sun.misc.Launcher$AppClassLoader.
Entre ellos, ExtClassLoader es responsable de cargar el paquete JAR en el directorio de extensión JRE ext, y AppClassLoader es responsable de cargar el paquete de clase en la ruta Classpath.
La prueba es la siguiente:
Copie el código de código de la siguiente manera:
paquete com.stopTalking.crazy;
clase pública TestClassLoader {
público estático vacío principal (String [] argumentos) {
//Obtener el cargador de clases del hilo actual
Cargador ClassLoader = Thread.currentThread().getContextClassLoader();
//Obtener el cargador de clases de la clase System
Cargador ClassLoader1 = System.class.getClassLoader();
//Obtiene el cargador de clases loader2 de esta clase TestClassLoader
Cargador ClassLoader2 = TestClassLoader.class.getClassLoader();
//Obtener la clase padre de loader2
ClassLoader cargador3 = loader2.getParent();
//Obtener la clase principal de la clase principal de loader2
ClassLoader cargador4 = loader3.getParent();
System.out.println(cargador);
System.out.println(cargador1);
System.out.println(cargador2);
System.out.println(cargador3);
System.out.println(cargador4);
}
}
Salida de consola:
Copie el código de código de la siguiente manera:
// El cargador de clases obtenido por la clase de subproceso actual es AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
// La clase System la carga el cargador raíz y no se puede acceder a ella en Java, por lo que es nula
nulo
//El cargador de clases de esta clase también es AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
nulo