An overview of the

Java files are eventually compiled into Class files, which need to be loaded into the JVM to run and use. The VIRTUAL machine loads the Class file describing the Class into memory, verifies the data, converts, parses and initializes the data, and finally forms Java types that can be directly used. This is the Class loading mechanism of virtual machines

In the Java language, class loading, linking, initialization, are carried out at runtime, although this will increase some performance overhead, but will make the Java program more flexible, Java can naturally dynamically extend the language features is to rely on the runtime dynamic loading and dynamic linking to achieve

Class loading timing

The whole life cycle of a class consists of seven stages: load, verify, prepare, parse, initialize, use, and unload. The three parts of verify, prepare, and parse are collectively referred to as connections

Which load, validation, preparation, initialization, unload the five phase is to determine the beginning of the order, the beginning of the class loading process must, in accordance with the order on track, while parsing is not sure, he can in some cases after initialization, note that there is a start, we say rather than on or complete, emphasize this point because these stages is the completion of the cross, Usually one phase is activated while another phase is in progress

Class loading process

Let’s take a look at the whole process of class loading

loading

Loading is a phase of class loading, so don’t confuse the two concepts

The load phase does three things

  • Gets the binary byte stream that defines a class by its fully qualified name
  • Transform the static storage structure represented by this byte stream into a method area runtime data structure
  • Generate a java.lang.class object in memory as an access point to the data of the class in the method area

These three definitions are not specific. The first one fetches the binary stream that defines this class by the fully qualified name of a class, without specifying where or how to fetch it. This gives the developer a lot of flexibility, such as

  • We can get it from ZIP, such as a JAR
  • We can get it from the Internet
  • Runtime computing generation is the scenario that makes the most use of dynamic proxy techniques
  • .

After the loading phase is complete, the binary stream outside the virtual machine is stored in the method area in the format required by the virtual machine, and then a java.lang.class object is instantiated, although it is an object, but it exists in the method area

validation

Validation is the first step in the connection phase, which ensures that the byte stream of the Class file contains information that meets the requirements of the current virtual machine and does not compromise the security of the virtual machine

To prepare

The preparation phase is the formal allocation of memory for class variables (static variables) and the setting of initial values. The memory used by these variables will be allocated in the method area. Here we focus on the initial values, such as the following variable

public static int value=123;
Copy the code

This phase assigns it a value of 0, not 123, because no Java methods have been executed yet. Assigning a variable to 123 is only executed during initialization, as listed below, with zero values for Java primitive data types

parsing

The parsing phase is the process by which the virtual machine replaces symbols in the constant pool with direct references

Initialize the

Initialization is the last step of class loading. In the previous class loading process, except for the loading stage, the user can control the other actions are dominated by the VIRTUAL machine. In the initialization stage, the Java program code defined in the class is actually executed

Regarding the initialization phase of class loading, there are only five scenarios where classes must be initialized in the VIRTUAL machine specification:

  • When an object is instantiated with the new keyword, a static field (excluding compile-time constants) is read or set, and a static method is called, the class load initialization process (the final phase of the class load) must be triggered.
  • When a class is called using reflection, it is initialized if the class is not already initialized
  • When initializing a class, if the parent class has not already been initialized, initialization of the parent class is triggered first
  • When the Java virtual machine starts, the user needs to specify a main class (the class containing the main method) to execute, and the virtual machine initializes this main class first
  • When using dynamic language support in JDK 1.7, if ajava.lang.invoke.MethodHandleThe final parsing result of the example isREF_getStatic, REF_putStatic, REF_invokeStaticWay to handle, and the method to handle the corresponding class does not initialize, must trigger the initialization (that don’t understand calculate, this is the new 1.7 dynamic language support, its key feature is the main body of its type checking process was conducted at runtime rather than compile time, this is a relatively larger topic, here for a moment to stop)

Classes and class loaders

The virtual machine implements the class-loading process of retrieving the binary stream that defines a class by its fully qualified name outside the Java virtual machine, allowing the user to decide how to retrieve the desired class. The block of code that implements this action is called a classloader

Although the Class loader is most used in the loading phase of a Class, its role in The Java program is not limited to the loading phase of a Class. For example, how to determine whether two classes are equal and only two classes are loaded by the same loader is meaningful. Otherwise, even if two classes come from the same Class file and are loaded by the same VIRTUAL machine, As long as the class loaders that load them are different, two classes must not be equal

Equality includes the equals method of the Class object and the Instance of keyword

Parental delegation model

From a Java virtual machine perspective, there are only two different class loaders

  • One is to start the Bootstrap ClassLoader, which is implemented in C++ as part of the virtual machine itself.
  • The other is all the other classloaders implemented by the Java language, independent of the virtual machine, and all inherited from java.lang.classloader

From the Java developer’s point of view, class loaders can be divided a little more subtly, and most use three of the following

Bootstrap ClassLoader (start column loader)

This class loader is responsible for loading libraries recognized by the virtual machine into the vm memory that are placed in the

\lib directory or in the path specified by the -xbootCLASspath parameter

Java virtual machine startup is accomplished by creating an initial class by starting the class loader, which is not accessible by Java code because it is implemented in C++

Extension ClassLoader

It is responsible for loading files in the

\lib\ext directory, or all libraries in the path specified by the java.ext.dirs system variable. Developers can use the extended class loader directly, the implementation class ExtClassLoader in Java

Application ClassLoader

Since this ClassLoader is the return value of the getSystemClassLoader method in ClassLoad, it is also called the system ClassLoader. It is responsible for loading the class libraries specified in the user’s classpath. Developers can use it directly if they do not customize the ClassLoader. This is the program’s default class loader, the implementation class AppClassLoader in Java

The hierarchy of class loaders shown in the figure below is called the parent delegate model. The parent delegate model requires that in addition to the top level of the starting class loader, the parent loader should have its own parent loader, which is implemented as a parent-child relationship, not as inheritance, but as a combination

Parents delegate the working process of the model

If a class loader has received the load request, he won’t try to load the first class, but to delegate the request to the parent class loader is complete, each level of the loader, so all the load request, should be introduced to the top of the boot loader, only the parent class loader feedback, unable to complete the load request, The loader will try to load it itself

Benefits of the parental delegation model

  • Avoid reloading. If it is already loaded, it does not need to be reloaded
  • Security, if you defineStringClass in place of the systemStringClass, which leads to risk, but in the parent delegate model,StringClass injavaThe virtual machine is loaded as soon as it starts, you customize itStringClasses are not loaded

Parent delegate model implementation source code

 protectedClass<? > loadClass(String name,boolean resolve)
        throws ClassNotFoundException{
            // First check if the class is loadedClass<? > c = findLoadedClass(name);if (c == null) {
                try {
                    if(parent ! =null) {
                        c = parent.loadClass(name, false);
                    } else{ c = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
                    // If the parent throws a ClassNotFoundException
                    // The parent class cannot load the class
                }

                if (c == null) {
                    // If the parent class cannot be loaded, call its own findClass to addc = findClass(name); }}return c;
    }

Copy the code

If not, call the parent’s loader. If the parent’s loader is empty, call the start loader. If the parent’s loader fails, call its own findClass load

In Java this

There are three types of classloaders, but there are more than three classloaders provided by the system. The ClassLoader is implemented as a parent-child relationship, not as an inheritance, but as a combination of classloaders.

These five classloaders are introduced as follows:

  • ClassLoader: is an abstract class, definedClassLoaderThe main functions of
  • SecureClassLoader: inherits abstract classesClassLoader, butSecureClassLoadernotClassLoaderThe implementation class is an extensionClassLoaderClass has been enhanced by adding permissionsClassLoaderThe safety of
  • UrlClassLoader: inherited fromSecureClassLoader, you can load classes and resources from JAR files and folders through the Url path
  • ExtClassLoader and AppClassLoader: inherited fromURLClassLoaderThey all areLauncherInner class of,LauncherJava Virtual Machine entry application,ExtClassLoaderandAppClassLoaderIs in theLauncherIs initialized in

The custom this

The ClassLoader provided by the system can only load classes in a specified directory. To load Class files in a folder on the network or disk, you need to customize a ClassLoader. There are two steps to implement ClassLoader

  • Define a class and inheritClassLoader
  • rewritefindClassMethod, and infindClassMethod calldefineClassmethods
public class CustomClassLoader extends ClassLoader {

    private String path;

    public CustomClassLoader(String path) {
        this.path = path;
    }

    @Override
    protectedClass<? > findClass(String name)throws ClassNotFoundException {
        Class clazz;
        / / comment 1
        byte[] data = loadClassData(name);
        if (data == null) {
            throw new ClassNotFoundException();
        } else {
            / / comment 2
            clazz = defineClass(name, data, 0, data.length);
        }

        return clazz;
    }

    private byte[] loadClassData(String name) {
        String fileName = getFileName(name);
        File file = new File(path,fileName);
        InputStream in=null;
        ByteArrayOutputStream out=null;
        try {
            in = new FileInputStream(file);
            out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length=0;
            while((length = in.read(buffer)) ! = -1) {
                out.write(buffer, 0, length);
            }
            return out.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(in! =null) { in.close(); }}catch (IOException e) {
                e.printStackTrace();
            }
            try{
                if(out! =null) { out.close(); }}catch(IOException e){ e.printStackTrace(); }}return null;
    }
    private String getFileName(String name) {
        int index = name.lastIndexOf('. ');
        if(index == -1) {// If no '.' is found, add the. Class at the end
            return name+".class";
        }else{
            return name.substring(index+1) +".class"; }}}Copy the code

The ClassLoader is a custom loader.

  • Note 1: The loadClassData method gets the bytecode array of the class file
  • Note 2: The defineClass method converts a class bytecode array into an instance of a class class

Let’s verify that it works

Define a hello.java file on your disk

package com.baidu.bpit.aibaidu.lib;

public class Hello {
    public void say(a) {
        System.out.println("helloword"); }}Copy the code

Use the command line to go to your disk and execute javac hello.java to generate the hello.class file. Then create a Java Library in AS to test

public class MyClass {

    public static void main(String[] args) {
        / / comment 1
        CustomClassLoader customClassLoader = new CustomClassLoader("/Users/v_renxiaohui01/Desktop");

        try {
            / / comment 2Class<? > aClass = customClassLoader.findClass("com.baidu.bpit.aibaidu.lib.Hello");

            if(aClass ! =null) {
                try {
                    Object o = aClass.newInstance();
                    System.out.println(o.getClass().getClassLoader());
                
                    Method say = aClass.getDeclaredMethod("say".null);
                    / / comment 3
                    say.invoke(o, null);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch(InvocationTargetException e) { e.printStackTrace(); }}}catch(ClassNotFoundException e) { e.printStackTrace(); }}}Copy the code
  • Comment 1: Pass the path to the class to load
  • Note 2: Loadclassfile
  • Note 3: Called by reflectionHello, the saymethods

Look at the log

com.baidu.bpit.aibaidu.lib.CustomClassLoader@677327b6
helloword
Copy the code

Reference: Understanding the Java Virtual Machine in Depth

Blog.csdn.net/itachi85/ar…