This is the 10th day of my participation in the More text Challenge. For more details, see more text Challenge

This article is participating in the “Java Theme Month – Java Development in action”. See the link to the event for more details


Related articles

Java Annotations and reflections: Java annotations and reflections

preface

Learning the class loading process makes it easier to understand the mechanics and principles of reflection.

The class loading process

1. Load

Load the class file bytecode contents into memory, convert the static data into a runtime data structure for the method area, and then generate a Java.lang.class object that represents the class.

2. Link

Merge the binary data of the class into the JRE.

  • Validation: To ensure that the class information loaded complies with the JVM specification without security concerns
  • Preparation: The phase of formally allocating memory for class variables (static) and setting default initial values for class variables, which will be allocated in the method area
  • Resolution: The process of replacing a symbolic reference (constant name) of a virtual machine constant pool with a direct reference (address)
3. Initialize: The JVM is responsible for initializing the class
  • The process of executing the class constructor () method. The class constructor () method is generated by an assignment action that automatically collects all class variables in the class during compilation and by merging statements in a static code block. (Class constructors are constructors that construct class information, not objects of the class.)
  • When initializing a class, if the parent class has not been initialized, the parent class must be initialized first
  • The virtual machine ensures that the () methods of a class are properly locked and synchronized in a multi-threaded environment

The picture is as follows:Test code:

public class test01 {
    public static void main(String[] args) {
        A a = newA(); System.out.println(A.num); }}class A{
    static {
        System.out.println("Static block initialization!");
        num = 500;
    }
    static Integer num = 100;
    public A(a){
        System.out.println("No-parameter construct initialization!"); }}Copy the code

The execution result is as follows:

Conclusion:

(1) set num to 500. (2) set num to 500

(2) We then execute the no-argument constructor, which is our new operation.

③ Run num = 100;

④ can be simple to get the class loading order!

Class initialization

Precode:

public class test01 {
    static {
        System.out.println("I'm a static block of code for the main class. The main class is loaded.);
    }
    public static void main(String[] args) {}}class A{
    static int b = 2;
    static {
        System.out.println("Superclass A is loaded ~"); }}class B extends A{
    static {
        System.out.println("Subclass B is loaded ~");
        b = 500;
    }
    static int m = 100;
    static final int M = 1;
}
Copy the code

This can be discussed in two ways: 1. Active references to classes (class initialization must occur)

  • When the VM starts, initialize the class where the main method resides
  • New An object of a class
  • Calls static members of the class (except for final constants) and static methods
  • Make a reflection call to the class using the methods of the java.lang.Reflect package
  • When initializing a class, if its parent class is not initialized, its parent class is initialized first
public static void main(String[] args) {
		// Active reference
        B b = new B();
    }
Copy the code

Results:

public static void main(String[] args) {
		// Reflection also generates active references
       Class.forName("com.dbright.Test.B");
    }
Copy the code

2. A passive reference to a class (class initialization does not occur)

  • When a static field is accessed, only the class that actually declares the field is initialized. For example, referencing a static variable from a parent class through a subclass does not cause the subclass to initialize
  • Defining a class reference through an array does not trigger the initialization of this class
  • References to constants do not trigger class initialization (constants are stored in the calling class’s constant pool during the linking phase).
public static void main(String[] args) {
		// Call the superclass static variable
      System.out.println(B.b);
    }
Copy the code

public static void main(String[] args) {
		// Define its own array
      B[] array = new B[5]; 
    }
Copy the code

public static void main(String[] args) {
		// Call its own static variables
      System.out.println(B.M);
    }
Copy the code

Class loaders

What the classloader does: it loads the class file bytecode contents into memory, converts the static data into a runtime data structure in the method area, and then generates a Java.lang. class object representing the class in the heap as an entry point for the data in the method area. Class loaders are divided into three main layers:

  • Bootstrap classloader: written in C++, the JVM’s own classloader is responsible for the Java platform core libraries and is used to load the core class libraries. The loader cannot directly obtain the Java\jdk1.8\jre\lib\rt.jar
  • Extension class loader: Is responsible for wrapping jars in the jre/lib/ext directory or in the -d java.ext.dirs specified directory into the working library
  • System class loader: the most commonly used loader is responsible for wrapping classes and jars in the directory referred to by java-classpath or -d java.class.path

Class cache: The standard JavaSE classloader can look for classes on demand, but once a Class has been loaded into the classloader, it will remain loaded (cached) for a period of time, although the JVM garbage collection mechanism can reclaim the Class objects.

public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        // Get the loader for the system class
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        System.out.println(loader);  //sun.misc.Launcher$AppClassLoader@18b4aac2

        // Get the superclassloader of the system class load --> extend the classloader
        ClassLoader parent = loader.getParent();
        System.out.println(parent);  //sun.misc.Launcher$ExtClassLoader@74a14482

        // Get the parent class loader of the extended class loader --> root class loader (C/C++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);  //null

        // Tests which loader loaded the current class
        ClassLoader classLoader = Class.forName("com.dbright.Test.Test02").getClassLoader();
        System.out.println(classLoader);  //sun.misc.Launcher$AppClassLoader@18b4aac2

        // Test who loaded the JDK inner classes
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);  //null

        // How do I get the path where the system class loader can load
        System.out.println(System.getProperty("java.class.path"));
        / * D: \ Software \ Java \ jdk1.8 \ jre \ lib \ charsets jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ deploy the jar. D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ access - bridge - 64. The jar. D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ cldrdata jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ DNSNS jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ jaccess jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ JFXRT jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ localedata jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ nashorn jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ sunec jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ sunjce_provider jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ sunmscapi jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ sunpkcs11 jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ ext \ zipfs jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ javaws jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ jce jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ JFR jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ JFXSWT jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ jsse jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ management - agent jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ plugin jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ resources jar; D: \ Software \ Java \ jdk1.8 \ jre \ lib \ rt jar; D:\NEU\learn\java\project\out\production\project; D: \ NEU \ learn \ Java \ project \ SRC \ com \ lib \ Commons - IO - 2.8.0. Jar; D: \ Software \ IntelliJ IDEA 2020.1.4 \ lib \ idea_rt jar * /
        // Parent delegate mechanism: does not use the lower-level defined class if the upper-level loader exists}}Copy the code

Parent delegation: does not use lower-level defined classes if the upper-level loader exists


I see no ending, but I will search high and low

If you think I blogger writes good! Writing is not easy, please like, follow, comment to encourage the blogger ~hahah