An overview of the

The entire life cycle of a class from the moment it is loaded into virtual machine memory to the moment it is unloaded from memory includes: loading

Loading, Verification, Preparation, Resolution, initialization

1. There are seven Initialization, Using and Unloading stages. Verify, prepare and parse

The three parts are collectively known as Linking.

During the initialization phase, the VIRTUAL machine specification specifies that there are only five cases in which classes must be “initialized” immediately

Loading, validation, and preparation of course need to start before that:

1) When new, getstatic, putstatic, or Invokestatic are encountered, if the class does not proceed

If the initialization is over, the initialization needs to be triggered first. The most common Java code scenario that generates these four instructions is: use

The new keyword instantiates an object, reads, or sets a static field of a class (modified by final and compiled)

To put results into static fields of the constant pool), and to call static methods of a class.

2) When a java.lang.reflect class is called using a java.lang.reflect method, if the class has not been initialized,

You need to trigger its initialization first.

3) When initializing a class, if the parent class has not been initialized, the parent class needs to be triggered first

Initialization of.

4) When the virtual machine starts, the user needs to specify a main class (the one containing the main () method) to execute.

The virtual machine initializes the main class first.

5) when using JDK 1.7 dynamic language support, if a Java lang. Invoke. Most MethodHandle instance

REF_getStatic, REF_putStatic, REF_invokeStatic, and REF_invokeStatic

If the class corresponding to the method handle has not been initialized, it needs to be initialized first.

Note:

For a static field, only the class that directly defines the field is initialized, so the parent class is referred to by its subclass

A static field that triggers initialization of the parent class but not of the subclass.

The constant HELLOWORLD, which is optimized for constant propagation at compile time, has been set to “hello”

World is stored in the constant pool of the NotInitialization class

References to constclass. HELLOWORLD are actually converted to references to the NotInitialization class’s own constant pool

Use.

That is, there are no ConstClass symbols referenced in the NotInitialization Class file

These two classes have no relationship after being translated into Class.

Loading stage

The VM needs to do the following three things:

1) Get 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 holds the various data of the Class as a method area

Access to.

validation

Is the first step in the join phase, which ensures that the information contained in the byte stream of the Class file matches

Requirements of the current VM and does not compromise VM security. But on the whole, the validation phase will be roughly

Complete the following four stages of verification: file format verification, metadata verification, bytecode verification, symbol reference verification

Certificate.

Preparation stage

Is the stage where you formally allocate memory for class variables and set their initial values. The memory used by these variables will be in the method

Area to allocate. There are two confusing concepts that need to be emphasized at this stage

Memory allocation includes only class variables (static modified variables), not instance variables, which will be allocated in the

Object instantiation is allocated in the Java heap along with the object. Second, the initial values mentioned here are “normally”

Is the zero value of the data type, assuming a class variable is defined as:

Public static int value=123;

The initial value of the variable value after the preparation phase is 0 instead of 123, because nothing has been executed yet

The putStatic instruction, which assigns a value of 123 to the putStatic instruction, is stored in the class constructor <

Clinit > () method, so assigning value to 123 will only take place during initialization. Table 7-1

Lists zero values for all basic data types in Java.

Public static final int value=123;

At compile time Javac will generate a ConstantValue attribute for the value, which the virtual machine will base on during the preparation phase

ConstantValue sets value to 123.

Parsing stage

Is the process by which the virtual machine replaces symbolic references in the constant pool with direct references

Class initialization phase

Is the last step in the class loading process. In the previous class loading process, the user application can pass except during the loading phase

Outside of the custom class loader, the rest of the action is completely led and controlled by the virtual machine. When you get to the initialization phase, it’s really

Start executing the Java program code defined in the class. In the preparation phase, the variable has been assigned the initial value required by the system.

In the initialization phase, class variables and other resources are initialized according to a programmer’s subjective plan made by the program, or

This can be expressed another way: the initialization phase is the process of executing the class constructor < clinit > () method. The <

The Clinit > () method is automatically collected by the compiler for assignment actions and static statement blocks (static{}) for all class variables in a class.

Block. The order in which the compiler collects the statements is determined by the order in which they appear in the source file.

The < clinit > () method is not required for a class or interface, and if a class does not have a static block, neither does it

If there are assignments to variables, the compiler may not generate the < clinit > () method for this class.

The virtual machine ensures that a class’s < clinit > () methods are locked and synchronized correctly in a multithreaded environment, if multiple

If a thread initializes a class at the same time, only one thread will execute the class’s < clinit > () method, and the rest

Threads need to block and wait until the active thread completes executing the < clinit > () method. If in a class < clinit

Long operations in the > () method can cause multiple processes to block.

Class loader

How to customize class loader, look at the code

Class loader for the system

For any class, its presence in the Java Virtual machine needs to be established both by the classloader that loads it and by the class itself

Each class loader has a separate class namespace. This sentence can be expressed more colloquially

Some: Comparing two classes for “equality” is only useful if they are loaded by the same classloader

Otherwise, even if the two classes come from the same Class file and are loaded by the same virtual machine, just load them

The two classes must not be equal.

The equals () method, isAssignableFrom, represents the Class objects of the Class

() method, isInstance () method, and object ownership using the instanceof keyword

Department decision and so on.

When customizing a ClassLoader subclass, there are two common approaches. One is to override the loadClass

The alternative is to override the findClass method. In fact, the two methods are essentially the same, after all, loadClass will also

Call findClass, but logically it is best not to modify the internal logic of loadClass directly. I suggest that the

The idea is to override the loading methods of custom classes only in findClass.

The loadClass method is where the parent delegate model logic is implemented, and tampering with this method will cause the model to be broken

Bad, easy to cause problems. Therefore, it is best to make small changes within the framework of the parental delegation model without breaking the original

There are stable structures. It also avoids the repetition of having to write parent delegates when overwriting the loadClass method itself

Code, in terms of the reusability of the code, it is always better not to modify this method directly.

Parental delegation model

From the Perspective of the Java virtual machine, there are only two different class loaders: one is to start the class loader

(Bootstrap ClassLoader), which is implemented in C++ language and is part of the virtual machine itself;

The other is all the other class loaders, which are implemented in the Java language and are independent of the virtual machine

And all inherit from the abstract java.lang.ClassLoader class.

Bootstrap ClassLoader: this ClassLoader is responsible for storing it in < JAVA_HOME > \lib

Directory, or the path specified by the -xbootCLASSPath parameter, and is recognized by the virtual machine

File name recognition, such as rt.jar, and libraries with incorrect names will not be loaded even if placed in the lib directory

Vm memory. The startup class loader cannot be referenced directly by Java programs. The user is writing a custom class loader

If you need to delegate the load request to the bootstrap classloader, use NULL instead.

Extension ClassLoader: This loader is created by Extension ClassLoader

Sun.misc.Launcher$ExtClassLoader, which loads the < JAVA_HOME > \lib\ext directory

, or all libraries in the path specified by the java.ext.dirs system variable, developers can use the extension directly

Class loader.

Application ClassLoader: This ClassLoader is called sun.misc.Launcher

$App – this implementation. Since this ClassLoader is getSystemClassLoader in ClassLoader

The return value of the () method, so it is also commonly called the system classloader. It is responsible for loading the user classpath

(ClassPath). Developers can use this class loader directly if the application does not have one

Class loaders have been customized, and this is usually the default class loader in the program.

All of our applications are loaded by these three types of loaders in conjunction with each other and, if necessary, by adding custom loaders

Class loader that has been defined.

The parent delegate model requires that all class loaders have their own parent class loaders, except for the top-level start class loaders

Device. The parent-child relationship between classloaders is not typically inherited, but both

Use Composition relationships to duplicate parent loader code.

One of the obvious benefits of using the parent-delegate model to organize the relationships between class loaders is that Java classes follow

Its classloaders come together with a hierarchy of priorities. For example, the java.lang.Object class, which is stored in

In rt.jar, any class loader that loads this class ends up delegating to the starting class at the top of the model

The loader loads, so the Object class is the same class in each classloader environment of the program. On the contrary, if

Instead of using the parent delegate model, each class loader loads it by itself, if the user writes a code called

Java.lang.Object classes, and put them in the ClassPath of the program, and several different ones will appear in the system

The Object class, the most basic behavior of the Java type system, would not be guaranteed, and the application would become chaotic.

Tomcat class loading mechanism

Tomcat itself is a Java project, so it also needs to be loaded by the JDK’s classloading mechanism and therefore must exist

Boot class loaders, extension class loaders, and application (system) class loaders.

The Common ClassLoader acts as the parent of Catalina ClassLoader and Shared ClassLoader

Shared classloaders may also have multiple Children classloaders, one WebApp ClassLoader

A WebApp ClassLoader actually corresponds to a Web application, and that Web application might have Jsp pages

These Jsp pages will eventually be loaded as class classes, so a Jsp classloader is also required.

Catalina ClassLoader, Shared ClassLoader, and Common at the code level

The entity classes corresponding to ClassLoader are actually URLClassLoader or SecureClassLoader

We simply divide these three classloaders logically based on the difference in content being loaded and the parent-child order of loading;

Both WebApp ClassLoader and JasperLoader have corresponding ClassLoader classes.

When Tomcat is started, several types of loaders are created:

1 Bootstrap The Bootstrap class loader loads the classes required to start the JVM, as well as the standard extension classes (located in jre/lib/ext)

Below)

2 System The System class loader loads classes that tomcat starts, such as bootstrap.jar, usually in Catalina.bat

Or specified in catalina.sh. It is in CATALINA_HOME/bin.

The Common class loader loads some Common classes that Tomcat uses and applies, located in

CATALINA_HOME/lib, for example, servlet-api.jar

4 WebApp Class loader After each application is deployed, a unique class loader is created. Class loader

Classes in jar files in WEB-INF/lib and classes in Web-INF /classes are loaded.

Method call details

parsing

The call target must be determined when the program code is written and the compiler compiles. Calls to such methods are called solutions

Analysis.

In the Java language, methods that meet the requirement of “compile-time knowable, run-time immutable” mainly include static methods

And private methods, which are directly associated with the type, and private methods, which cannot be accessed externally

The dot determines that none of them can override another version by inheritance or otherwise, so they are all suitable for class loading

Parse.

Static dispatching

See method overloading more often.

“Human” is the Static Type of a variable, or the Apparent Type

Type), followed by “Man” is called the Actual Type of the variable

The difference is that the static type changes only when used, the variable itself is static

The type is not changed, and the final static type is known at compile time; The result of the actual type change is running

The compiler does not know what the actual type of an object is when it compiles the program.

The code defines two variables of the same static type but different actual type, but the virtual machine (or compiler, to be precise)

Overloading is determined by the static type of the parameter rather than the actual type. And static typing is compile-time

Therefore, at compile time, the Javac compiler decides which overloaded version to use based on the static type of the parameter

Ben, so sayHello (Human) was selected as the call target. All rely on static types to locate method implementations

Ben’s dispatch action is called static dispatch. A typical use of static dispatch is method overloading. Static dispatch occurs at the compile level

Segment, so determine that statically dispatched actions are not actually performed by the virtual machine.

Dynamic dispatch

Static types man and woman, both Human variables, are executed when the sayHello () method is called

Different behavior, and the variable man executes different methods in the two calls. The reason for this phenomenon is quite clear

It turns out that the actual types of the two variables are different.

In the implementation, the most common means is to create a virtual method table for the class in the method area. The virtual method table holds each

The actual entry address of the method. If a method is not overridden in a subclass, the address in the subclass’s virtual method list

The entry is identical to the address entry of the same method in the parent class, pointing to the implementation entry of the parent class. If I override this in my subclass

The address in the subclass method table will be replaced by the entry address pointing to the subclass implementation version. In the PPT picture, Son

Overrides all methods from Father, so Son’s method table has no arrows pointing to Father data. but

Neither Son nor Father overrides methods from Object, so all of their method tables inherit from Object

All methods refer to the data type of Object.

Stack – based bytecode interpretation execution engine

The instruction stream the Java compiler outputs, basically, is a stack-based instruction set architecture, with most of the instructions in the instruction stream

Are zero-address instructions that rely on operand stacks to work. with

Register-based instruction sets, the most typical is the x86 two address instruction set, colloquially speaking, is now we

An instruction set architecture directly supported in mainstream PCS that relies on registers for work.

The simplest example is to compute the result of “1+1” using the two instruction sets separately. The stack-based instruction set is this

It looks like:

iconst_1

iconst_1

iadd

istore_0

After the two iconst_1 instructions push the constant 1 onto the stack, the iadd instruction adds the two values at the top of the stack

Istore_0 puts the top of the stack into Slot 0 of the local variable table.

If register-based, the program might look something like this:

Mov eax, 1

The add eax, 1

The MOV instruction sets the value of the EAX register to 1, and the add instruction increments the value by 1. The result is stored in EAX

In the register.

The main advantage of the stack-based instruction set is that it is portable; registers are provided directly by the hardware on which the program depends

Registers are inevitably constrained by hardware. The main disadvantage of stack architecture instruction sets is that execution speed is relatively low

A little slower. The instruction set of all major physical machines is a register architecture which also confirms this point from the side.