This is the 10th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

preface

The last INSTALLMENT of the JVM series talked about the RUNTIME data region of the JVM, but before you can enter the runtime data region, Class files need to enter the JVM through the classloading mechanism; This article deals with the life cycle of classes in the JVM

Previous recommendations:

“JVM Series” – takes you through the JVM runtime data area

Before the class is officially used, it goes through three stages: loading, connection, and initializationThere are three phases: verification, preparation, and resolutionIt is important to note that these five phases, while started sequentially, are not completed sequentially, and are usually invoked or activated during the execution of one phase, and the parsing phase may occur after initialization (to support runtime binding in the Java language).


1. Loading phase

The JVM specification defines that during the load phase, the virtual machine needs to do three things:

  1. Gets the binary stream defined by a class through its fully qualified name
  2. Converts the static storage structure represented by the byte stream to the runtime data structure of the method area
  3. Generate an in-memory representation of the classjava.lang.ClassObject that serves as an entry point for this data in the method area

Virtual Machine Specifications These three points are not specific, so virtual machines can be implemented flexibly. For example, “get a class’s defined binary byte stream by its fully qualified name” doesn’t specify where and how to get it

In addition to the virtual machine directly responsible for the creation of array types, non-array types in the stage of reading binary byte streams can be customized by the developer, we can customize a class loader to get binary byte streams, can be from the network, JAR packages, local path…


2. Connection stage

2.1 validation

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

The four stages of verification are completed:

File format validation: Verifies that the byte stream complies with the specification of the Class file format, for example:

  1. Whether by magic number0xCAFEBABEAt the beginning
  2. Whether the primary and secondary versions are within the processing range of the current VM
  3. Whether constants in the constant pool have unsupported types

Metadata validation: Performs semantic analysis of the information described by the bytecode (note: compared to the semantic analysis at the JavAC compilation stage) to ensure that the information described conforms to the Requirements of the Java language specification. Such as:

  1. Does this class have a parent class (exceptjava.lang.Object)
  2. Does this class inherit from a class that is not allowed to inherit (a class that is final modified)?
  3. Whether the fields and methods in the class conflict with the parent class
  4. If the class is not abstract, does it implement all the methods required in its parent class or interface

Bytecode validation: Through data flow and control flow analysis, determine that program semantics are legal and logical

Symbolic reference validation: Ensures that the parsing action is performed correctly

The validation phase is important, but not necessary, and has no impact on the program runtime. If the referenced class is repeatedly validated, consider using * -xverifyNone * to turn off most of the class validation measures to shorten the virtual machine class load time


2.2 to prepare

In the preparation phase, memory is formally allocated for class variables and initial values are set for class variables, which will be allocated in the method area

The following points should be noted for this stage:

  1. In this case, only class variables (static) are allocated, not instance variables, which are allocated in the Java heap along with the object when it is instantiated
  2. The initial value set here is typically the default zero value for the data type (such as 0, NULL, false, etc.), rather than the value given explicitly in Java code
  3. Suppose a class variable is defined as:public static int value = 1; The variablevalueThe initial value after the preparation phase is 0, not 1, because no Java methods have yet been executed and value is assigned to 1put staticInstructions are stored in the class constructor after the program is compiled<clinit>()Method, so thevalueAn action assigned to 1 will only be performed during the initialization phase


2.3 analytical

During the resolution phase, the VIRTUAL machine replaces symbolic references in the constant pool with direct references. The parsing action is mainly for class, interface, field, class method, interface method, method type, method handle, and call qualifier

Symbolic References: A Symbolic reference uses a set of symbols to describe the referenced target. A symbol can be a literal in any form, as long as it can uniquely locate the target. Symbolic references are independent of memory layout, so the referenced object does not necessarily need to have been loaded into memory. The memory layouts of the various virtual machine implementations can differ, but the symbolic references accepted must be consistent because the literal form of symbolic references is already clearly defined in the Class file format

Direct References: A Direct reference is either a pointer to a target, a relative offset, or a handle that indirectly locates the target. Direct references are related to the memory layout implemented by the virtual machine. The translation of the same symbolic reference in different virtual machines is not the same. If there is a direct reference, it must already be in memory


3. Initialization

The initialization phase is the execution of the initialization method

() method, where the JVM actually begins to execute the bytecode defined in the class

For the

() method:

  • clinit> ()Methods are thread-safe, so class initialization in a multi-threaded environment can cause multiple processes to block, and the blocking is difficult to detect
  • <clinit>()Methods are generated by the compiler automatically collecting the assignment actions of all class variables in the class and merging them with statements in static statement blocks.The order in which the compiler collects the statements is determined by the order in which the statements appear in the source file. Variables defined before and after a static block can only be accessed. Variables defined after a static block can be assigned to, but cannot be accessed
  • In the preparation phase, variables are given initial values, but in the initialization phase, all variables have to be reinitialized in user-written code. To put it another way, the initialization phase executes the class constructor<clinit>()Methodological process

During the initialization phase, the VM strictly specifies that there are only six conditions under which classes must be initialized:

  1. When faced withnewgetstatic,putstaticinvokestaticThese four direct code instructions; Four instructions correspond to one anotherWhen an instance object is created, when a program accesses a static variable of a class, when a program assigns a value to a static variable, or when a program calls a static method
  2. usejava.lang.reflectWhen a package method makes a reflective call to a class, it triggers an initialization if the class is not initialized
  3. Initializes a class, firing the initialization of its parent class if it is not already initialized
  4. When the VM starts, the user needs to define a main class (includingmainMethod), the virtual machine initializes this class first
  5. In the use ofMethodHandleVarHandleThis is considered a lightweight reflection call mechanism that must be used in order to use these two callsfindStaticVarHandleTo initialize the class to be called
  6. When an interface is defined with the new JDK8 Default method, the interface must be initialized first if an implementation class of the interface is initialized

JVM initialization steps:

  1. If the class has not already been loaded and connected, the program loads and connects the class first
  2. Initialize the class’s immediate parent class if it has not already been initialized
  3. If there are initialization statements in the class, the system executes them in turn


4. Remove

An uninstalled Class is a Class object of that Class that is GC

A class completes its lifecycle in several ways:

  1. All instances of the class have been GC, which means that there are no instances of the class in the heap.
  2. The class is not referenced anywhere else
  3. An instance of the class loader for this class has been GC

Therefore, classes loaded by the JVM’s own classloaders are not unloaded during the JVM’s life cycle; But classes loaded by our custom class loaders can be unloaded


Reference

JVM Fundamentals – Java class loading mechanism

JavaGuide: Class loading process

In-depth understanding of the JVM class loading mechanism