1. Function of class loading subsystem

  • The Class loading subsystem is responsible for loading Class files from the file system or network. Class files have specific file identifiers at the beginning of the file.
  • The ClassLoader is only responsible for loading the Class file, and whether it can run is determined by the Execution Engine.
  • The loaded class information is stored in a piece of memory called a method area. In addition to Class information, the method area stores runtime constant pool information, possibly including string literals and numeric constants (this constant information is a memory map of the constant pool portion of the Class file)

Note: Runtime constant pools, as shown in the following code

public class StackStructure {

    public static void main(String[] args) {
        int a = 2;
        int b = 3;
        intc = a + b; }}Copy the code

Decompiled partial output

Constant pool:
   #1 = Methodref          #3.#21         // java/lang/Object."<init>":()V
   #2 = Class              #22            // com/nasuf/jvm/StackStructure
   #3 = Class              #23            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lcom/nasuf/jvm/StackStructure;
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               args
  #14 = Utf8               [Ljava/lang/String;
  #15 = Utf8               a
  #16 = Utf8               I
  #17 = Utf8               b
  #18 = Utf8               c
  #19 = Utf8               SourceFile
  #20 = Utf8               StackStructure.java
  #21 = NameAndType        #4: #5          // "<init>":()V
  #22 = Utf8               com/nasuf/jvm/StackStructure
  #23 = Utf8               java/lang/Object
Copy the code

The above constant pool information becomes the runtime constant pool when it is loaded into memory at run time.

2. The ClassLoader role

  • A class file exists on the local hard disk, which can be interpreted as a template drawn on paper by the designer. The final template is executed as a binary stream loaded into the JVM to instantiate n identical instances from this file.
  • The class file is loaded into the JVM, called the DNA metadata template, and placed in the method area;
  • In the. Class file -> JVM -> eventually called the metadata template, this process requires a transporter (the ClassLoader) that acts as a Courier

3. Class loading process

3.1 loading

  1. Gets the binary byte stream that defines a class by its fully qualified name;
  2. Convert the static storage structure represented by this byte stream to the runtime data structure of the method area;
  3. Generate a java.lang.Class object in memory that represents the Class and acts as an access point for the Class’s various data in the method area.

How to load a class file

  • Load directly from the local system
  • This parameter is obtained over the network. The typical scenario is a Web Applet
  • Read from zip package, become the future jar, WAR format basis
  • Runtime computational generation, most commonly used: dynamic proxy technology
  • Generated by other files, typical scenario: JSP application
  • Extracting class files from a proprietary database is rare
  • Obtained from encrypted files, a typical protection against class files being decompiled

3.2 the link

3.2.1 Verify

  • The purpose is to ensure that the byte stream of the class file contains more information that meets the requirements of the current VM, ensuring the correctness of the loaded classes and not harming the VM security.
  • It mainly includes four kinds of verification: file format verification, metadata verification, bytecode verification, symbol reference verification; For example, to view the following bytecode files, the bytecode should start with CA FE BA BE:

3.2.2 Prepare

  • Allocate memory for class variables and set the default initial value of the class variable, which is zero;
  • Static with final is not included here, because final is allocated at compile time and initialized explicitly during preparation;
  • There is no instance variable allocation initialization, class variables are allocated in the method area, and instance variables are allocated to the Java heap along with the object phase

3.2.3 Resolve (Resolve)

  • The process of converting symbolic references in a constant pool to direct references;
  • In fact, parsing is often performed by the JVM after initialization;
  • A symbolic reference is a set of symbols that describe the referenced object. The literal form of symbolic reference is clearly defined in the Java Virtual Machine Specification’s class file format. Direct drinking is a pointer to a target directly, a relative offset, or a handle to a target indirectly.
  • Parsing actions are for classes or interfaces, fields, class methods, interface methods, method types, and so on. Corresponding to CONSTANT_Class_info, CONSTANT_Fieldref_info, and CONSTANT_Methodref_info in the constant pool

3.3 the initialization

  • The initialization phase is the execution of the class’s constructor method

    ();
  • This method does not need to be defined, but is a combination of the javac compiler’s automatic assignment of all class variables in the phone class and statements in the static code block.
  • Constructor methods execute instructions in the order in which statements appear in the source file.
  • < Clinint >() differs from the constructor of the class (correlation: the constructor is

    () from the virtual machine perspective);

View the following code bytecode information:

Modify the code to look again, and the <clinit>() method merges the values shown initialized in the code:

Modify the code to view the assignment process:

The <clinit>() method does not exist in the bytecode if there are no static variables or blocks of code in the class:

  • If the class has a parent class, the JVM guarantees that

    () of the parent class has completed before

    () of the subclass is executed.

  • The virtual machine must ensure that a class’s

    () method is locked synchronously in multiple threads; For example, after two threads are started, only one thread will initialize the DeatThread class

4. Classification of class loaders

4.1 an overview of the

  • The JVM supports two types of classloaders, Bootstrap classloaders (written in a non-Java language) and user-defined classloaders (written in Java language).
  • A custom ClassLoader is a class of loaders defined by a developer in a program, but the Java virtual machine specification defines all classloaders derived from the abstract ClassLoader as custom classloaders. Extension classloaders and application classloaders are custom classloaders that indirectly inherit the ClassLoader class.

ExtClassLoader.class

AppClassLoader.class

Print out class loaders for each layer:

4.2 starting the ClassLoader (Bootstrap ClassLoader)

  • This class load is implemented in C/C++ and is nested within the JVM;
  • It is used to load Java’s core libraries (JAVA_HOME/jre/lib/rt.jar, resources.jar or sun.boot.class.path) to provide classes that the JVM itself needs;
  • Does not inherit from java.lang.ClassLoader, no parent loader;
  • Load extension classes and application classloaders and designate them as their parent class loaders;
  • For security reasons, Bootstrap starts the class loader to load only classes whose package names start with Java/Javax/Sun, etc

4.3 Extension ClassLoader

  • Java language, implemented by Sun.misc.Launcher$ExtClassLoader;
  • Derived from the ClassLoader class;
  • The parent class loader is the startup class loader.
  • Load the class libraries from the directory specified by the java.ext.dirs system property, or from the JRE /lib/ext subdirectory (extension directory) of the JDK installation directory. If user-created jars are placed in this directory, they will also be automatically loaded by the extended class loader

4.4 Application ClassLoader (System class loader, AppClassLoader)

  • Java language, implemented by Sun.misc.Launcher$AppClassLoader;
  • Derived from the ClassLoader class;
  • The parent class loader is the extension class loader.
  • It is responsible for loading the class libraries under the path specified by the environment variable classpath or the system property java.class.path;
  • Class loading is the default class loader in the program, generally speaking, Java applications are completed by it to load classes;
  • The class loader can be obtained by using the ClassLoader#getSystemClassLoader() method

4.5 User-defined class loaders

In everyday Java application development, class loading is almost performed by the above three class loaders in coordination with each other, we can also customize the class loaders, if necessary, to customize the way the class is loaded.

4.5.1 Purpose of Customizing class loaders

  • Isolation load class
  • Modify the class loading method
  • Extended load source
  • Prevent source code leakage

4.5.2 Steps for customizing class loaders

  1. Developers can implement their own classloaders by inheriting the abstract java.lang.ClassLoader class to meet special needs.
  2. Before JDK1.2, it was common to inherit the ClassLoader class and rewrite the loadClass() method to implement custom classloading classes. However, after JDK1.2, it is no longer recommended to override the loadClass() method. Instead, I suggest that you write your custom classloading logic in the findClass() method;
  3. When writing a custom class loader, if you don’t have too complicated requirements, you can inherit the URLClassLoader class directly. This way, you can avoid writing the findClass() method and the way to get the bytecode stream, making the custom class loader writing simpler

4.6 about this

The ClassLoader class is an abstract class, and all subsequent classloaders inherit from it (excluding the launcher ClassLoader).

Method names describe
getParent() Returns the superclass loader for the class loader
loadClass(String name) Load a Class named name that returns an instance of the java.lang.Class Class
findClass(String name) Find a Class named name that returns an instance of the java.lang.Class Class
findLoadedClass(String name) Find the loaded Class named name and return an instance of the java.lang.Class Class
defineClass(String name, byte[] b, int off, int len Converts the contents of byte array B to a Java Class, returning an instance of the java.lang.Class Class
resolveClass(Class<? > c) Connects to a specified Java class

5. Parent delegation

The Java virtual machine loads class files on demand, which means that it loads its class files into memory to generate class objects when the class is needed. In addition, when loading a class file, the Java VIRTUAL machine adopts the parental delegation mode, that is, the request to the parent class processing, which is a kind of task delegation mode.

5.1 Working Principles

  1. If a classloader receives a classload request, it does not load the request itself. Instead, it delegates the request to the parent class’s loader.
  2. If the parent class loader still has its parent class to load, then further delegate up, recursively, the request will eventually reach the top level of the start class loader;
  3. If the parent class loader can complete the classloading task, it returns successfully. If the parent class loader cannot complete the task, the child loader will try to load itself. This is the parent delegate pattern

5.2 Sandbox Security Mechanism

For example, if we create a package named java.lang with the same name as String. Java and execute the main method, we will get the following error:

Java \lang\String. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \ string. jar: java.lang \String. Because the String class is loaded in the rt.jar package, this ensures the protection of the Java core source code. This is the sandbox safety mechanism

If we create another class under the custom java.lang package that is not defined under the rt.jar package, we get the following error:

5.3 advantage

  • Avoid reloading classes
  • Protect program security and prevent the core API from being tampered with

6. Other

6.1 Two necessary conditions for whether two class objects are the same class:

  • The full class name of the class must be the same, including the package name;
  • The ClassLoader that loads this class must be the same; In other words, even if these two class objects come from the same class file and are loaded by the same VIRTUAL machine, they are not equal in the JVM as long as they are loaded by different ClassLoader instances

6.2 References to class loaders

The JVM must know whether a type is loaded by the boot class loader or by the user class loader. If a type is loaded by a user class loader, the JVM stores a reference to that class loader in the method area as part of the type information. When resolving a reference from one type to another, the JVM needs to ensure that the classloaders for both types are the same

6.3 Active and passive use of classes

  • Active use (divided into 7 cases)
    • Create an instance of the class
    • Accesses or assigns a value to a static variable of a class or interface
    • Call a static method of a class
    • Reflection, such as class.forname (“com.nasuf. Test “)
    • Initialize a subclass of a class
    • Classes that are identified as startup classes when the Java virtual machine starts
    • JDK 7 began to offer a dynamic language support: Java. Lang. Invoke. Analytical results REF_getStatic MethodHandle instance, REF_putStatic, REF_invokeStatic handle corresponding class does not initialize, is initialized
  • Except for these seven cases, any other way of using Java classes is considered a passive use of the class and does not result in class initialization (as mentioned above during class loading)