1. An overview of the

The virtual machine loads the Class file describing the Class data into memory. After verification, preparation, parsing, and initialization, a Java type can be used directly. This process is called the virtual machine Class loading mechanism.

Java language class loading, connections, initialization is done at runtime, and completing these steps in the compiler compared to other languages, Java class loading strategy will make the class loading increased slightly some performance overhead, but the benefits of change is for the Java program provides a high degree of flexibility, this flexibility is embodied in the following two aspects:

  • ● Interface oriented applications can specify the actual implementation classes at run time.
  • ● You can customize class loaders to dynamically load binary streams from the network or elsewhere at run time as part of program code.

2. Timing of class loading

2.1 Class loading Sequence

The entire life cycle of a class from load to unload includes: load, validate, prepare, parse, initialize, use, and unload. The verification, preparation and analysis stages can be collectively referred to as connection. The order of loading, validation, preparation, initialization, and unloading is determined. The class loading process starts in this order, while the order of parsing may start before or after initialization.

2.2 Cases in which classes must be initialized

Java virtual machine specification did not say when the first phase of class loading, loading, but for when to class loading process of the initialization phase, the specification is made strict rules, when meet the following conditions, the virtual machine must be class initialization (class loading, validation, preparation needs to start before initialization).

  • 1. When new, getstatic, putstatic, and Invokestatic are encountered, and the class has not been initialized. (Note: The most common scenarios for these four instructions are: instantiate an object using the new keyword, get static fields of the class (except static fields of final type), set static fields of the class, and call static methods of the class.)
  • 2. Use reflection to load classes that have not yet been initialized.
  • 3. Initialize the current class. If the parent class is not initialized, initialize the parent class first.
  • 4. The user-specified main class (that is, the class that calls the main() method).

2.3 Interface Initialization

Interface initialization is slightly different from class initialization: when a class is initialized, its parent class is required to have been initialized. The interface does not require that the parent interface be initialized. Instead, the parent interface is initialized only when the parent interface is needed (for example, a constant referencing the parent interface).

3. Passive references to classes

The behavior described in section 2.2 above is called an active reference to a class and is characterized by initialization of the class. There is also a passive reference to a class that does not initialize the class after referencing it. Here are some examples of passive referencing:

3.1 Subclass access to static fields of the parent class does not result in subclass initialization

public class SuperClass {
	static {
		System.out.println("superClass init!");
	}
	public static int value = 123;
}
Copy the code
public class SubClass extends SuperClass {
	static {
		System.out.print("subclass init!"); }}Copy the code
public class NotInit { public static void main(String[] args) { System.out.print(SubClass.value); }}Copy the code

After the above code is run, it does not print “subclass init!” , just output “superClass init!” . For static field access, only the class that directly defines the field is initialized. Therefore, accessing static fields defined in the parent class by a subclass will only result in the parent class being initialized and the subclass not initialized.

3.2 Referencing a class by an array definition does not cause the class to be initialized

public class NotInit { public static void main(String[] args) { SuperClass[] arr = new SuperClass[10]; }}Copy the code

The above code will not run without “superclass init!” , indicating that the class is not initialized.

3.3 References by the current class to other class constants do not cause other classes to be initialized.

public class ConstantClass {
	static {
		System.out.println("ConstantClass init!");
	}
	public static final int value = 10;
}
Copy the code
public class NotInit { public static void main(String[] args) { System.out.println(ConstantClass.value); }}Copy the code

The above code does not print “ConstantClass init!” . When NotInit references ConstantClass’s constants, the ConstantClass’s constants are dumped into the ConstantClass’s constant pool at compile time, which means that NotInit already owns the constant itself, so there is no need to reference other classes’ constants and therefore no need to initialize other classes.