preface

The five steps of class loading were described earlierTo review

  • Load, connect, initialize, use, and unload classes.

  • There are 3 sub-steps in connection:

    • Validation: To ensure the correctness of the classes being loaded.
    • Preparation: Allocates memory for static variables of the class and initializes them to default values. (int 0, Boolean false).
    • Parsing: Converts symbolic references in a class to direct references.
  • Initialization is assigning the correct initial value to a static variable of a class.

    • Only active use of a class is initialized.

further

Let’s start with a simple piece of code

  • code
public class PrepareAndInit {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1: "+Singleton.counter1);
        System.out.println("counter2: "+Singleton.counter2); }}class Singleton{
    protected static int counter1;
    protected static int counter2 = 0;
    private static Singleton singleton = new Singleton();
    private Singleton(a){// Private constructor external cannot be directly new
        counter1++;
        counter2++;
    }
    public static Singleton getInstance(a){
        returnsingleton; }}Copy the code
  • The results of

How about rewriting the code and moving the static variable counter2 under the constructor

  • code
package com.jvmstudy.classloading;

public class PrepareAndInit {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1: "+Singleton.counter1);
        System.out.println("counter2: "+Singleton.counter2); }}class Singleton{
    protected static int counter1;
    private static Singleton singleton = new Singleton();
    private Singleton(a){// Private constructor external cannot be directly new
        counter1++;
        counter2++;
    }
    protected static int counter2 = 0;
    public static Singleton getInstance(a){
        returnsingleton; }}Copy the code
  • The results of

The reasons for this result

Singleton singleton = Singleton.getInstance();
Copy the code
  • Calling a static method of a class causes the class to be initialized.

However, prior to the initialization phase, the preparatory actions in the connection phase are performed

Preparation stage

  • Allocate memory for static variables and assign default values (int 0, Boolean false, reference null)
  • Preparation stage
class Singleton{
    protected static int counter1;
    private static Singleton singleton = new Singleton();
    private Singleton(a){// Private construct, the outside of the class cannot be directly new
        counter1++;
        counter2++;
    }
    protected static int counter2 = 0;
    public static Singleton getInstance(a){
        returnsingleton; }}Copy the code
  • Counter1 = 0;
  • The singleton = null;
  • Constructors do not execute;
  • Counter2 = 0;

Initialization phase

  • Assign the correct values to static variables that the programmer assigns manually.
class Singleton{
    protected static int counter1;
    private static Singleton singleton = new Singleton();
    private Singleton(a){// Private construct, the outside of the class cannot be directly new
        counter1++;
        counter2++;
    }
    protected static int counter2 = 0;
    public static Singleton getInstance(a){
        returnsingleton; }}Copy the code
  • Counter1 = 0; (Still 0)
  • Singleton = reference to the Singleton instance object;
  • The constructor is executed because new Singleton() is used;
    • Inside the constructor
    • Counter1 = 1;
    • Counter2 = 1;
  • Given the constructor, counter2 is given 0 (programmer written); That is, counter2 goes from 1 to 0;
  • The end result:
    • Counter1 = 1;
    • Counter2 = 0;
  • conclusion
    • Initialization is performed from the top down and is preceded by a preparation phase (assigning default values to static variables). ;

Again, class loading

These are concepts.

  • Type loading: Reading binary Java types into the Java virtual machine.
  • The connection: There are 3 substeps
    • Validation: Check bytecode (.class) files.
    • Preparation: Allocates memory for class variables and sets default values. But on arrival initialization. Previously, class variables were never initialized to true initial values.
    • Parsing: Parsing is the process of finding symbolic references to classes, interfaces, fields, and methods in the constant pool of a type and replacing these symbolic references with direct references
  • Initialization: Assigns the correct initial value to a class variable.
  • Class to instantiateThe Java compiler generates at least one instance initialization method for every class it compiles. In Java class files, this instance initialization method is called<init>. The Java compiler generates one constructor for each class in the source code<init>Methods.

The final product of class loading

  • The end product of Class loading is an in-memory Class object.
  • The Class object encapsulates a Class’s data structure in the method area and provides Java programmers with an interface to access the data structure in the method area.

The timing of initialization

  • When a Java virtual machine initializes a class, it requires that all of its parent classes have been initialized,But this rule does not apply to interfaces.
    • When a class is initialized, the interface it implements is not initialized first.
    • When an interface is initialized, its parent interface is not initialized first.
    • Therefore, a parent interface is not initialized because its child interface or implementation class is initialized. Only the first time a program uses a static variable of a particular interface causes that interface to be initialized.