In this article, we will look at the class loading mechanism and the parent delegation model.

  • An overview of the
  • Class loading process
  • Class loader & parent delegate model

1. An overview of the

A. JVM Class loading mechanism: A VM loads data describing a Class from a Class file to the memory, verifies, transforms, and initializes the data, and finally forms Java types that can be directly used by VMS.

B. Features: Runtime class loading. That is, in the Java language, the loading, wiring, and initialization of types are done at runtime, sacrificing some performance overhead for the flexibility of Java programs.

JVM runtime dynamic loading + Dynamic wiring -> Dynamic extension features of the Java language


2. The whole process of class loading

The life cycle of a class starts from being loaded into vm memory and ends when it is unloaded from memory. There are seven stages:

  • Loading
  • Verification
  • Preparation
  • Resolution
  • Initialization
  • Using
  • 2. Unloading is a class.

Among them, validation, preparation and parsing are collectively referred to as Linking, and the process is shown as follows:

Note:

  • The “load” -> “verify” -> “prepare” -> “initialize” -> “unload” phases are in a definite order, while “parse” may start after “initialize” to support runtime binding in the Java language.
  • The above phases are usually intermixed, such that one phase is invoked or activated during execution of another phase.

The following sections describe each of these phases.


A. to load

Task:

  • Gets the binary byte stream that defines the class by its fully qualified name. Read from ZIP packages, get from the network, generate by runtime computation, generate from other files, read from a database, and so on……
  • The static storage structure represented by the binary byte stream is converted to the runtime data structure of the method area, which is self-defined by the virtual machine implementation.
  • Generates an in-memory representation of this classjava.lang.ClassObject that acts as an external interface for the program to access data of these types in the method area.

B. to verify

  • Is the first step in the connection phase, and is a significant part of the JVM classloading subsystem.
  • Purpose: To ensure that the byte stream in the Class file meets the requirements of the current VM and does not compromise vm security.

The validation phase is necessary because it directly determines whether the JVM can tolerate malicious code, but not necessarily because it has no effect on the program runtime. Consider using the -xVerify: None parameter to turn off most of the class validation to shorten the virtual machine class load time.

  • The inspection process includes the following four partsphase:
    • File format validation:
      • Verify that the byte stream complies with the Class file format specification and can be processed by the current version of the virtual machine.
      • Purpose: To ensure that the input byte stream is properly parsed and stored in the method area in a format that describes the information of a Java type. The binary byte stream is stored in the method area of memory only after it is guaranteed to pass this validation, so the next three validation phases are all based on the method area rather than the byte stream.
    • Metadata validation:
      • Content: Semantic analysis of the information described by bytecode to ensure that the information described conforms to the requirements of the Java language specification.
      • Objective: To verify the semantics of class metadata to ensure that there is no metadata that does not conform to Java language specifications.
    • Bytecode verification: Indicates the verification processThe most complicatedA phase of.
      • Content: Verifies and analyzes the method body of a class to ensure that the methods of the verified class do not cause events that harm VM security during running.
      • Objective: To determine that program semantics are legal and logical by analyzing data flow and control flow.
    • Symbolic reference verification:
      • Content: Checks for match information outside the class itself, such as various symbolic references in the constant pool.
      • The purpose is to ensure that the parse action executes properly, and if it fails to pass symbolic reference validation, one will be thrownjava.lang.IncompatibleClassChangeErrorA subclass of exceptions.
      • Note: This validation occurs when the virtual machine converts symbolic references to direct references, in the “parse” phase.

C. to prepare

Task:

  • Allocate memory for class variables: Because the variables are allocated by the method area, only class variables are included, not instance variables, which will be allocated in the Java heap along with the object when it is instantiated.
  • Set the initial value of the class variable: usually zero.

D. parsing

  • As mentioned earlier, the parsing phase is when the virtual machine willConstant poolThe process by which symbolic references in are replaced by direct references.
    • Symbolic referenceSymbolic References: Use a set of symbols to describe the target referenced.
      • It can be any literal, as long as it is used to unambiguously locate the target.
      • Regardless of the memory layout of the virtual machine implementation, because the literal form of symbolic references is explicitly defined in the Class file format of the Java Virtual Machine specification, the acceptance of symbolic references is consistent across virtual machine implementations, even if the memory layout is different.
    • Direct reference(Direct References) :
      • It can be a pointer directly to the target, a relative offset, or a handle that indirectly locates the target.
      • Depending on the memory layout implemented by the virtual machine, the same symbolic reference is generally translated into a direct reference on different virtual machine instances.
  • When it happens: The JVM determines whether to parse symbolic references in the constant pool as soon as the class is loaded by the loader, or to wait until a symbolic reference is about to be used.
  • Parsing action: there are seven types of symbols and their corresponding seven constant types in the constant pool
    • Class or interface(CONSTANT_Class_info)
    • field(CONSTANT_Fieldref_info)
    • Class method(CONSTANT_Methodref_info)
    • Interface methods(CONSTANT_InterfaceMethodref_info)
    • Method type(CONSTANT_MethodType_info)
    • Method handles(CONSTANT_MethodHandle_info)
    • Call the point qualifier(CONSTANT_InvokeDynamic_info)

For example, if the current code is in class D, parse an unparsed symbolic reference N into a direct reference to a class or interface C in three steps:

  • If C is not an array type: the JVM will pass the fully qualified name representing N to the class D loader to load C. During the loading process, the loading actions of other related classes may be triggered due to the requirements of metadata verification and bytecode verification. As soon as any exception occurs in the load process, the parsing process fails.
  • If C is an array type and the array element type is an object: the JVM also loads array element types according to the above rules.
  • If nothing is wrong with the above steps: C is now a valid class or interface in the JVM, but it needs to be done before parsing is completeSymbolic reference verificationTo check whether D has the access permission to C. If it is found that the access permission is not available, it will be thrownjava.lang.IllegalAccessErrorThe exception.

E. initialization

  • Is the final step in the class-loading process and begins the actual execution of the Java bytecode defined in the class. However, in the previous class loading process, except for the “load” stage, user applications can participate in the custom class loader, and the rest stages are dominated and controlled by virtual machines.
  • With the “preparation” phaseDistinguish between:
    • Preparation stage: Variable assigned initial zero value.
    • Initialization phase: Initializes class variables and other resources, or executes class constructors, according to Java program Settings<clinit>()In the process.

< Clinit >() : generated by combining the assignment action of all class variables in the class that the compiler automatically collects with statements in the static statement block static{}.

  • Is thread-safe and is properly locked and synchronized in a multi-threaded environment.
  • For a class or interfacenonMandatory, if a class has no static block and no assignment to a variable, the compiler may not generate for that class<clinit>().
  • Interfaces differ from classes in that they are implemented<clinit>()The parent interface does not need to be executed first<clinit>()The parent interface is initialized only when a variable defined in the parent interface is used. In addition, the implementation class of the interface does not execute the interface when initialized<clinit>().
  • In the virtual machine specification, there are five and only five cases where classes must be “initialized” immediately:
    • encounternew,getstatic,putstaticorinvokestaticThese four bytecode instructions;
    • usejava.lang.reflectWhen a package’s method makes a reflection call to a class;
    • When initializing a class, if the parent class is not initialized, the initialization of the parent class is triggered first.
    • When the VM starts, specify a main class to execute. The VM initializes it first.
    • When using JDK1.7’s dynamic language support, if ajava.lang.invoke.MethodHandleThe final parsing result of the instance isREF_getStatic,REF_putStatic,REF_invokeStatic, and the class corresponding to this method handle has not been initialized. Initialization must be triggered first.

3. Classloader & Parent delegate model

Each classloader has a separate class namespace, which is used not only to load the class, but also as a unique identifier within the JVM along with the class itself. So the only way to compare two classes for equality is to see if they are loaded by the same classloader. Even if they come from the same Class file and are loaded by the same JVM, the two classes must not be equal as long as they are loaded by different classloaders.

A. Class loader

From the PERSPECTIVE of the JVM, there are two types of classloaders:

  • Start the class loader(the Bootstrap this)
    • byC++The language implementation is part of the virtual machine itself.
    • Responsible for loading and storingThe < JAVA_HOME > \ libDirectory, or by-XbootclasspathThe virtual machine-recognized class library in the path specified by the parameter.
    • Cannot be directly referenced by Java programs. If the custom class loader wants to delegate load requests to the bootstrap class loader, null can be used instead.
  • Other class loaders: byJavaLanguage implementations, independent of the virtual machine, and all inherited from abstract classesjava.lang.ClassLoader, can be directly referenced by Java programs. Several common ones:
    • Extend the class loaderThe Extension (this)
      • bysun.misc.Launcher$ExtClassLoaderThe implementation.
      • Responsible for loadingThe < JAVA_HOME > \ lib \ extIn the directory or byjava.ext.dirsAll class libraries in the path specified by the system variable.
    • Application class loader(this)
      • isThe defaultClass loader, yesClassLoader#getSystemClassLoader()Return value of, so also calledSystem class loader.
      • bysun.misc.Launcher$App-ClassLoaderThe implementation.
      • Responsible for loading the libraries specified on the user’s classpath.
    • Custom User ClassLoader: you can customize a User ClassLoader if the previous classes cannot be loaded.

The relationship between the above types of loaders is shown below:

Note that although array classes are created directly by the JVM rather than through the class loader, they are closely related to the class loader because the element types of array classes are ultimately created by the class loader.

B. Parents Delegation Model

  • Represents a hierarchical relationship between class loaders.
  • Premise: Except for the top start class loader, the other class loaders should have their own parent class loaders, and the relationship between them is generally not implemented by Inheritance, but by Composition to copy the code of the parent class loader.
  • How it works: When a classloader receives a classload request, it delegates the request to the parent classloader and passes it up to the top level starting classloader. Only when the parent loader reports that it cannot complete the load request will the child loader attempt to load it itself.
  • Note: This is not a mandatory constraint model, but a kind of loader implementation recommended by Java designers to developers.
  • advantagesThe: class comes with its classloaderpriorityCan ensure the stable operation of Java program; Simple implementation, all implementation code is centralized inJava. Lang. This loadClass ()In the.

For example, some classloaders that load the java.lang.Object class end up delegating the load to the top bootstrap classloader, so that the Object class is the same class in each classloader environment of the program. Instead, there would be multiple Object classes, the most basic behavior in the Java type system would not be guaranteed, and the application would become chaotic.