En Java, primero escribe un archivo .java que luego se compila en un archivo .class durante el tiempo de compilación. Java es capaz de cargar clases en tiempo de ejecución. La confusión es cuál es la diferencia entre «cargar» e «inicializar». ¿Cuándo y cómo se carga e inicializa una clase Java? Puede ilustrarse claramente utilizando un ejemplo sencillo a continuación.
¿Qué significa decir «cargar una clase»?
C / C ++ se compila primero en código de máquina nativo y luego requiere un paso de vinculación después de la compilación. Lo que hace el enlace es combinar archivos fuente de diferentes lugares y formar un programa ejecutable. Java no hace eso. El paso similar a la vinculación para Java se realiza cuando se cargan en JVM.
Diferentes JVM cargan clases de diferentes maneras, pero la regla básica es cargar clases solo cuando son necesarias. Si hay otras clases requeridas por la clase cargada, también se cargarán. El proceso de carga es recursivo.
¿Cuándo y cómo se carga una clase Java?
En Java, las políticas de carga las gestiona un ClassLoader. El siguiente ejemplo muestra cómo y cuándo se carga una clase para un programa simple.
TestLoader.java
package compiler; public class TestLoader { public static void main(String[] args) { System.out.println("test"); } } |
A.java
package compiler; public class A { public void method(){ System.out.println("inside of A"); } } |
Aquí está la jerarquía de directorios en eclipse:
Al ejecutar el siguiente comando, podemos obtener información sobre cada clase cargada. La opción «-verbose: class» muestra información sobre cada clase cargada.
java -verbose:class -classpath /home/ron/workspace/UltimateTest/bin/ compiler.TestLoader
Parte de la salida:
[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/] test [Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
Ahora si cambiamos TestLoader.java a:
package compiler; public class TestLoader { public static void main(String[] args) { System.out.println("test"); A a = new A(); a.method(); } } |
Y ejecute el mismo comando nuevamente, la salida sería:
[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/] test [Loaded compiler.A from file:/home/xiwang/workspace/UltimateTest/bin/] inside of A [Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
Podemos ver la diferencia resaltada en rojo. Una clase se carga solo cuando se usa. En resumen, se carga una clase:
- cuando se ejecuta el nuevo bytecode. Por ejemplo, SomeClass f = new SomeClass ();
- cuando los códigos de bytes hacen una referencia estática a una clase. Por ejemplo, System.out.
¿Cuándo y cómo se inicializa una clase Java?
Una clase se inicializa cuando se usa por primera vez un símbolo de la clase. Cuando se carga una clase, no se inicializa.
JVM inicializará la superclase y los campos en orden textual, inicializará los campos finales estáticos primero y dará a cada campo un valor predeterminado antes de la inicialización.
La inicialización de instancia de clase Java es un ejemplo que muestra el orden de ejecución de campo, campo estático y constructor.
Referencias:
1. Cargador de clases de Java
2. Carga de clases de Java
3. Inicialización de clases y objetos