An overview of the

I don’t know if you feel this way, but for the JVM, the principles seem to be understandable, but it’s easy to forget and hard to practice. There is a very suitable sentence for the JVM, heard a lot of truth, lack of still bad life.

The purpose of this article is to practice validation class initialization. Mainly through the following points to describe:

  1. Overview of JVM class loading
  2. Several cases in which a class is initialized
  3. What does the class do during initialization
  4. The validation class is initialized
  5. Several cases that are easily confused and do not initialize

Overview of JVM class loading

If you have Java development experience, you probably know that the JVM loading process is as follows:

  1. Load phase (load class bytecode file content via local classpath, network, etc.).
  2. Link stage (subdivided into verification, preparation, parsing three sub-stages.)
    • Verification phase is responsible for verifying whether the bytecode file content conforms to JVM specifications (such as magic number, version number, etc.)
    • The preparation phase allocates memory for static properties
    • The parsing phase is responsible for parsing conforming references into direct references (the parsing phase is not sequential, as long as it is done before the bytecode is executed)
  3. Initialization phase

Several cases in which a class is initialized

The JVM specification does not specify when a class will be loaded. The specification specifies that the class initialization phase can be triggered in the following ways:

  1. Start the class
  2. New instruction target class
  3. Subclass initialization causes the parent class to be initialized
  4. Call a static method or field of the target class
  5. A subclass causes the interface it implements to be initialized
  6. Reflected in the Class. ForClassName
  7. MethodHandler

What does the class do during initialization

Knowing that a class can be initialized in some of the situations described above, what happens during initialization?

  1. A basic type property declared as final static, marked as a constant value by the virtual machine, and initialized with the specified value.
  2. Other property assignments declared static and static code blocks are placed in the Clinit () method by the Java compiler.

The validation class is initialized

Let’s do some tests to verify that the above situation is initialized.

  1. Test the new instruction target class
public class TestClassInit1 { private static class Person { static { System.out.println("person static code"); } } public static void main(String[] args) { new Person(); }} person static codeCopy the code
  1. Subclass initialization causes the parent class to be initialized
public class TestClassInit2 { private static class Person { static { System.out.println("Person static code"); } } private static class Student extends Person { static { System.out.println("Student static code"); } } public static void main(String[] args) { new Student(); }} Person static code Student static codeCopy the code
  1. Call a static method or field of the target class
public class TestClassInit3 { private static class Person { static int num = 1024; static { System.out.println("Person static code"); } static void print() { System.out.println("Person static method"); } } public static void main(String[] args) { // System.out.println(Person.num); Person.print(); Person static code Person static methodCopy the code
  1. Call a static method or field of the target class
public class TestClassInit4 { private static class PersonHolder { static { System.out.println("holder static code"); } } private interface Person { PersonHolder OBJ = new PersonHolder(); */ default void print() {system.out.println ("person print"); */ default void print() {system.out.println ("person print"); } /** * methods do not have a default implementation, subclass initialization does not cause the interface to be initialized */ void print2(); } private static class Student implements Person { static { System.out.println("Student static code"); } @Override public void print2() { System.out.println("student print"); } } public static void main(String[] args) { new Student(); }} holder static code Student static codeCopy the code
  1. The class.forname method causes initialization
public class TestClassInit5 { private static class Student { static { System.out.println("Student static code"); }} public static void main(String[] args) throws Exception {// Causes initialization of class.forname ("TestClassInit5$Student"); }} Student static codeCopy the code

Several cases that are easily confused and do not initialize

  1. Declares that array type properties are not initialized
public class TestClassNotInit1 { private static class Student { static { System.out.println("Student static code"); } } public static void main(String[] args) throws Exception { Student[] s = new Student[1]; }} will not outputCopy the code
  1. Class is not initialized
public class TestClassNotInit2 { private static class Student { static { System.out.println("Student static code"); } } public static void main(String[] args) throws Exception { Class clz = Student.class; System.out.println(clz); // The following code also does not cause the class to initialize System.out.println(clz.getSimplename ()); System.out.println(clz.getSuperclass()); System.out.println(clz.getDeclaredFields()); System.out.println(clz.getDeclaredMethods()); }} output:  class TestClassNotInit2$Student Student class java.lang.Object [Ljava.lang.reflect.Field; @7229724f [Ljava.lang.reflect.Method;@4c873330Copy the code

conclusion

For several cases of initialization whether reading books or online blogs are more or less understand, in fact, practice or harvest some details. It is not serious to say that class initialization causes interface initialization.