Class loading mechanism and reflection

Class 1 loading, connection and initialization

Class 1.1 loading process

When a program uses a class, if the song class has not been loaded into memory, the system will initialize the class through the steps of loading, connecting and initialization. Generally, the class loader does not need to wait until the first use to load objects. The java virtual machine allows the virtual machine to load some classes in advance.
Class loading: read the class file of the class, such as memory, and create a Java Lang. class object. That is, when the program uses any class, the system will create a Java Lang. class object.

1.1.1 loading

class is loaded into memory. The process is completed by the loader. The process is a parental delegation mechanism,

1.1.2 linking

After the Class is loaded, the system generates a corresponding Class object for it, and then enters the connection phase, which is responsible for merging binary data into the large JRE. The connection process is divided into the following three stages:

  • verification: verify whether the file complies with the provisions of the JVM
  • preparation: assign default values to static member variables
  • resolution:
    Resolve symbolic references such as classes, methods and attributes to direct references;
    Resolve various symbol references in the constant pool into direct references to memory addresses such as pointers and offsets;

1.1.3 initialization

It is not until the initialization phase that the java code defined in the class is actually executed. This stage calls the initialization code to assign the static variable to the initial value.

Assignment process
Load - > Default - > initial
New - > apply for memory - > assign default value - > assign initial value

Class 1.2 loader

The class loader is responsible for The class file is loaded into memory and the corresponding Java. XML file is generated Lang. class object.

1.2.1 loader classification

  • Start class loader: Bootstrap ClassLoader, which is responsible for loading Java_ The class in home \ lib or specified in the path or system value through the - Xbootclasspath parameter.
  • Extension ClassLoader: Extension ClassLoader, which is responsible for loading Java_ In the home \ lib \ ext directory, or through Java The ext.dirs parameter specifies the class in the path.
  • System ClassLoader: System ClassLoader, which is responsible for loading classes on the user path.
  • User defined class loader
    The JVM loads classes through the parental delegation model.

1.2.2 class loading mechanism

  • Global delegation: when a Class loader is responsible for loading a Class, the Class loader will also be responsible for loading other classes referenced and dependent on the Class, unless it is displayed that another loader is used for loading.
  • Parent Class delegate: first let the parent Class loader try to load the Class. Only when the parent Class loader cannot load the Class will it try to load the Class from its own loading path.
  • Caching mechanism: ensure that all loaded classes will be cached. When the program needs a Class, it will be obtained from the cache first. When the Class object does not exist in the cache, the system will read the binary file corresponding to the Class, convert it into a Class object and store it in the cache.

2 reflection

2.1 get class object

There are three ways to get a Class:

  • Use class Forname ("full path of class");
  • Use object getClass() method;
  • Call the class attribute of a class to get the corresponding class object

2.3 creating objects

There are two ways to generate objects using reflections:

  • Use the newInstance() method of the Class object to create an instance corresponding to the Class object (this method requires the Class object to correspond to the default constructor of the Class);
  • First use the Class object to obtain the specified Constructor object, and then call the newInstance() method of the Constructor object to create the corresponding instance of the Class object.
/**
 * @author : wind-myf
 * @desc : Object pool factory
 * @version : 1.0
 */
public class ObjectPoolFactory {
    /**
     * Define a map storage object, key object name, value object
     */
    private static Map<String,Object> objectMap = new HashMap<>();

    /**
     * Factory initialization
     * read file
     */
    public void initFactory(String fileName) {

        // Read file contents
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(fileName);
            Properties properties = new Properties();
            properties.load(fileInputStream);
            // Loop create object
            for (String name : properties.stringPropertyNames()) {
                objectMap.put(name,createObject(properties.getProperty(name)));
            }
        } catch (IOException | IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("Exception reading file, file name:" + fileName);
        }

    }

    /**
     * Create an object with reflection based on the full name of the object
     * And stored in the map
     * @param className Class full name
     */
    private Object createObject(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        // Get class object
        Class<?> clazz = Class.forName(className);
        return clazz.newInstance();
    }

    /**
     * Object acquisition
     */
    public Object getObject(String className){
        return objectMap.get(className);
    }

    public static void main(String[] args) {
        ObjectPoolFactory objectPoolFactory = new ObjectPoolFactory();
        // Absolute path required here
        objectPoolFactory.initFactory("src/main/java/com/myf/wind/base/reflectdemo/object.txt");
        Object drum = objectMap.get("drum");
        System.out.println("drum = " + drum);
        Object guitar = objectMap.get("guitar");
        System.out.println("guitar = " + guitar);

    }
}

2.4 jdk dynamic proxy based on reflection (AOP Implementation)

jdk dynamic Proxy generates jdk dynamic Proxy class and dynamic Proxy object through Proxy class and InvocationHandler interface. In the following example, MyProxyFactory obtains the Proxy class through reflection, implements method interception in custom MyInvocationHandler, and executes custom interception methods before and after method interception.

AOP implementation example:

/**
 * @author : wind-myf
 * @desc : JDK Dynamic agent
 */
public class JdkProxyDemo {
    public static void main(String[] args) {
        Flower target = new FlowerImpl();
        Flower flower = (Flower)MyProxyFactory.getProxy(target);
        flower.sayFlowering("spring");
        flower.queryColors();
    }

}

/**
 * Agent factory
 */
class MyProxyFactory{
    /**
     * Get proxy class
     */
    public static Object getProxy(Object target){
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.setTarget(target);
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), handler);
    }
}

/**
 * Flower interface
 */
interface Flower {

    void sayFlowering(String season);

    List<String> queryColors();

}

/**
 * Implementation class
 */
class FlowerImpl implements Flower{

    @Override
    public void sayFlowering(String season) {
        System.out.println("this is beautiful season : " + season);
    }

    @Override
    public List<String> queryColors() {
        System.out.println("this is queryColors-----");
        List<String> colors = new ArrayList<>();
        colors.add("green");
        colors.add("red");
        colors.add("blue");
        return colors;
    }
}

class MyInvocationHandler implements InvocationHandler{

    /**
     * Object to be proxied
     */
    private Object target;


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Execute method 1 before executing the original method
        FlowerUtil.flowerMethod1();
        Object result = method.invoke(target, args);
        // Execute interception method 2 after the execution of the original method is completed
        FlowerUtil.flowerMethod2();
        return result;
    }

    public void setTarget(Object target) {
        this.target = target;
    }
}

/**
 * Interception method tool class
 */
class FlowerUtil{
    /**
     * Interception method I
     */
    public static void flowerMethod1(){
        System.out.println("FlowerUtil--method 1------");
    }
    /**
     * Interception method II
     */
    public static void flowerMethod2(){
        System.out.println("FlowerUtil--method 2------");
    }
}

3 remarks

demo git address of the above code:
https://github.com/windmyf/study-demo/blob/main/base-demo/src/main/java/com/myf/wind/base/reflectdemo/JdkProxyDemo.java

Keywords: Java Back-end AOP Class reflection

Added by trevHCS on Fri, 07 Jan 2022 06:25:08 +0200