Java advanced features -- reflection mechanism (Part 2)

In the advanced feature of Java - reflection mechanism (Part 1), many examples of reflection are written, and the understanding of Class may still be a little confused. Let's try to analyze it from the perspective of memory.

Java Memory

 

As can be seen from the above figure, Java divides memory into heap, stack and method area, of which the method area is a special heap.

Heap: new objects and arrays are usually stored in the heap, which can be shared by all threads and will not store other object references.

Stack: store the basic variable type (which will contain the specific value of the basic type) and the variable of the reference object (which will store the specific address of the reference in the heap).

Method area: it can be shared by all threads, including all class and static variables‘

Class loading process (just understand)

When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through the following three steps:

 

Step 1: load the class The class file is read into memory, and these static data are transformed into the data structure of the method area runtime, and then a Java. Java.xml file representing this class is generated Lang. class object. This process is done by the class loader.

Step 2 (link): merge the binary code of Java classes into the JVM's running environment JRE, which is divided into the following three steps:

> verification: ensure that the information of the loaded class complies with the JVM specification and there are no security problems.

> preparation: the stage of formally allocating memory for class variables (static) and setting the default initial value of class variables. These memory will be allocated in the method area.

> resolution: the process of replacing the symbolic reference (constant name) in the virtual machine constant pool with a direct reference (address).

Part III (initialization): the JVM is responsible for initializing the class. The process is as follows:

> the process of executing the class constructor < clinit > () method. The class constructor < clinit > () method is generated by automatically collecting the assignment actions of all class variables of the class and combining the statements in the static code block during compilation. (class constructor is the constructor that constructs class information, not the constructor that constructs this kind of object)

> when initializing a class, if you find that its parent class has not been initialized, you need to trigger its parent class to initialize first.

·> virtual opportunity ensures that a class < clinit > () method is locked and synchronized correctly in a multithreaded environment.

Example test:

package test;

import java.lang.annotation.ElementType;

public class Test{
    public static void main(String[] args) {
        A a = new A();
        
        System.out.println(a.m);
        
        /*
         * 1.When loaded into memory, a class object corresponding to the class will be generated
         * 2.Link: after the link ends, m=0
         * 3.initialization
         *         <clinit>(){
         *             System.out.println("A The static code block of the class is loaded "");
                    m=300;
                    m=100;
         *         }
         *     Last: m=100
         */
        
    }
    
}


class A{
    static {
        System.out.println("A The static code block of the class is loaded");
        m=300;
    }
    
    static int m=100;
    
    public A() {
        System.out.println("A Class's parameterless constructor initialization");
    }
    
    
}

 

Operation results:

 

Class initialization

When will class initialization occur?

1. Active reference of class (class initialization is bound to occur)

>When the virtual machine starts, first initialize the class where the main method is located.

>New is an object of a class.

>Call static members (except final constants) and static methods of the class.

>Using Java The method of lang.reflect package calls the reflection of the class.

>When initializing a class, when the parent class is not initialized, its parent class will be initialized first.

Example (2-1):

package test;


//When will the test class be initialized
public class Test{
    static {
        System.out.println("main Class is loaded");
    }
    
    public static void main(String[] args) throws ClassNotFoundException {
        
        //Active reference
        //Son son = new Son();
        
        
        //Reflection also produces active references
        Class.forName("test.Son");
        
        
        //Both output results are the same
        /*
         *   The result is:
         *  main Class is loaded
         *    Parent class loaded
         *   Subclass loaded
         */
    }
    
}

class Father{
    
    static int b = 1;
    
    static {
        System.out.println("Parent class loaded");
    }
}

class Son extends Father{
    static {
        System.out.println("Subclass loaded");
        m = 300;
    }
    
    static int m = 100;
    
    static final int M = 1;
}

 

The print result is:

 

 2. Passive reference of class (class initialization will not occur)

>When accessing a static domain, only the class that actually declares the domain will be initialized. For example, when a static variable of a parent class is referenced through a subclass, the subclass will not be initialized.

>The array defined by this class will not be initialized.

>Reference constants do not trigger the initialization of this class (constants are stored in the constant pool of the calling class in the link phase).  

Example (change the main method of example 2-1):

public static void main(String[] args) throws ClassNotFoundException {
        //Methods that do not generate references
        //System.out.println(Son.b);
        
        //Son[] sons = new Son[10];
        
        System.out.println(Son.M);
    }

 

Test the execution results one by one!

Class loader

>The function of class loader: load the bytecode content of class file into memory, convert these static data into the runtime data structure of method area, and then generate a Java. Net file in the heap Lang. class object, as the access entry of class data in the method area.

>Class caching: standard Java SE classes can find classes as required, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time, but the JVM garbage collection mechanism (gc) can recycle these class objects.

 

 

Role of class loader

The function of class loader: load classes into memory.

The JVM specification defines the following types of class loaders:

 

>Bootstrap classloader: written in C + +, it is the class loader of the JVM. It is responsible for the core library of the Java platform and is used to load the core class library (rt.jar). This loader cannot be obtained directly.

>Extension ClassLoader: it is responsible for the jar package or - D Java under jre\lib\ext directory Ext.dirs package the jar of the specified directory into the studio.

>System ClassLoader: responsible for java -classpath or - D Java class. The classes and jar s in the directory referred to in path are packaged into the work, which is the most commonly used loader.

For example, get loader:

package test;



public class Test{
    
    public static void main(String[] args) throws ClassNotFoundException {
        //Get class loader
        ClassLoader c1 = ClassLoader.getSystemClassLoader();
        System.out.println(c1);
        
        //Gets the parent class loader of the class loader-->Extended class loader
        ClassLoader c2 = c1.getParent();
        System.out.println(c2);
        
        //Gets the parent class loader of the extended class loader-->Root loader(C/C++ Tip:Cannot get return NULL)
        ClassLoader c3 = c2.getParent();
        System.out.println(c3);
        
        //Test which class the current loader is loaded by
        ClassLoader c4 = Class.forName("test.Test").getClassLoader();    
        System.out.println(c4);
        
        //test JDK Which loader is loaded by
        ClassLoader c5 = Class.forName("java.lang.Object").getClassLoader();        
        System.out.println(c5);
        
        //How to get the path that the system class loader can load
        System.out.println(System.getProperty("java.class.path"));
        
        //Parent delegation mechanism learning link(https://blog.csdn.net/shy415502155/article/details/88167713)
        
        
        /*
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;
         C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;
         G:\test\bin
         */
    }
    
}

 

Print results:

 

Tags: Annotation

Posted by fme on Mon, 23 May 2022 15:18:03 +0300