Send you the following learning materials, the end of the article has the way to get







Get acquainted with the JVM specification

Look at the JVM from three perspectives

Insert the picture description here

Summary of the JVM

  • JVM: Java Virtual Machine
  • The so-called virtual machine refers to: through software simulation with complete hardware system functions, running in a completely isolated environment of the computer system
  • The JVM is an instruction set that simulates Java bytecode through software. It is the environment in which Java programs run

Key features of the JVM

  • Find and load class files using ClassLoader
  • Interpret the bytecode into instructions and execute them, providing the environment in which class files are run
  • Perform runtime memory allocation and garbage collection
  • Provide a platform for interacting with the hardware

Virtual machines are a Java platform-independent safeguard

Insert the picture description here

The role of the JVM specification and its core

The role of JVM specification

  • The Java Virtual Machine specification provides a specification for compiling Java technology code for different hardware
  • The specification makes Java software platform-independent because it is compiled against a “normal machine” that is a virtual machine
  • This “general machine” can be simulated and run on a variety of existing computer systems in software, or implemented in hardware

The main content of the JVM specification definition

  • Bytecode instruction set
  • The format of the Class file
  • Data types and values
  • Runtime data area
  • The stack frame
  • Special methods
  • The class library
  • abnormal
  • Start, load, link, and initialize the virtual machine

Class bytecode parsing

Overview of the Class file format

  • The Class file is the input to the JVM, and the structure of the Class file is defined in the Java Virtual Machine specification. The Class file is the foundation of the JVM’s platform independent and technology independent implementation
  1. Unsigned number: The basic data type, with U1, U2, U4, and U8 representing a few bytes of unsigned number
  2. Table: A data type consisting of several unsigned and other tables, usually ending with “\_info”
  3. A Class file is a set of 8-byte byte streams of data items arranged in compact order
  4. For data items occupying more than 8 bytes of space, they should be divided into multiple 8 bytes for storage according to the way of high-ranking first
  5. There are only two types in the Class file format: unsigned numbers and tables

The format of the Class file

  • The javap tool generates an informal “virtual machine assembly language” in the following format:
  • [[]]… ] [comment]
  • Is the subscript of an instruction opcode in an array that stores the Java virtual machine code for the current method in bytes; It can also be the byte offset equivalent to the start of the method
  • It’s the mnemonic for the instruction, the operand, the comment at the end of the line

Class file format description

  • Constant \_pool\_count: Begin with 1
  • Different constant types are distinguished by the tag, which is followed by the corresponding info structure is different
  • L stands for objects, [for arrays, and V for void
  • Stack: The depth of the operation stack when the method is executed
  • Locals: Storage space required for local variables (slot)
  • Slot is the smallest unit used by the virtual machine to allocate memory for local variables
  • Args \_size: The number of arguments (1) that are passed to the instance method by default, locals also reserve a slot for this

ASM

Refer to the post

Summary of the ASM

  • ASM is a Java bytecode manipulation framework that can be used to dynamically generate classes or enhance the functionality of existing classes
  • ASM can either directly generate binary class files or dynamically change the class behavior before the class is loaded into the virtual machine. After ASM reads information from the class file, it can change the class behavior, analyze the class information, and even generate new classes on request
  • Many current frameworks, such as CGlib, Hibernate, and Spring, use ASM directly or indirectly to manipulate bytecode

ASM programming model

  • Core API: Provides an event-based programming model. This model does not require the entire class structure to be read into memory at once, so it is faster and requires less memory, but it is more difficult to program this way
  • Tree API: Provides a tree-based programming model. This model requires that the entire structure of a class be read into memory at once, so this approach requires more memory and is simpler to program

The Core of the ASM API

  • The ability to manipulate bytecode in the ASM Core API is based on the ClassVisitor interface. Each method in this interface corresponds to each item in the class file
  • ASM provides three classes based on the ClassVisitor interface for class file generation and conversion
  • ClassReader: ClassReader parses the class bytecode of a class
  • ClassAdapter: ClassAdapter is an implementation class for ClassVisitor that implements the functionality to be changed
  • ClassWriter: ClassWriter is also an implementation class for ClassVisitro, which can be used to output the changed bytecode
  • ASM provides us with Asmifier tool to help the development, you can use Asmifier tool to generate ASM structure for comparison

Class loading, wiring, and initialization

Class loading and class loaders

  • Classes are loaded into the JVM from the beginning to the unloaded memory, and the entire life cycle is shown below:

Insert the picture description here

  • Load: Finds and loads the binary data of the class file
  • Connecting: Merges binary data from a class that has been read into memory into the JVM runtime environment. This involves the following steps:
  • Validation: Ensure the correctness of the loaded class
  • Prepare: Allocates memory for static variables of the class and initializes them
  • Converts a symbolic reference in a constant pool to a direct reference
  • Initialize: Assigns initial values to static variables of a class

What class loading is to do

  • Gets the binary byte stream of a class by its fully qualified name
  • Turn binary bytes into a runtime data structure for a method area
  • A java.lang.Class object is created on the heap to encapsulate the Class’s data structure inside the method area and to provide an interface to the data structure inside the method area

How the class is loaded

  • The most common way: load from the local file system, or from an archive file such as a JAR
  • Dynamic: Compile Java source files dynamically to a class
  • Other methods: Internet download, load from a proprietary database, etc

Class loader

  • Loaders that come with the Java Virtual Machine include the following:
  • BootstrapClassLoader BootstrapClassLoader
  • PlatformClassLoader JDK8: ExtensionClassLoader
  • Application class loader (AppClassLoader)
  • User-defined loader: is a subclass of java.lang.ClassLoader. Users can customize the way classes are loaded. Custom class loaders are loaded in the last order of all system class loaders

Class loader relationships

Insert the picture description here

The class loader uses

Class loader description

  • Startup Class Loader: Used to load the base module classes of the startup, such as java.base, java.management, java.xml, etc
  • Platform classloaders: Used to load platform-specific modules such as: java.scripting, java.compiler *, java.corba *, etc
  • Application class loaders: Used to load applica-level modules such as jak.piler, jdk.jartool, jdk.jshell, etc. It also loads all the class libraries in the CLASSPATH path
  • JDK8: Start the class loader: It is responsible for loading virtual machine-recognized libraries in the path specified by

    /lib, or -xbootclasspath (identified by name, such as rt.jar, for unrecognized files)
    \_home>
  • JDK8: Extended Class Loader: It is responsible for loading all class libraries in the path specified by

    /lib/ext, or the java.ext.dirs system variable
    \_home>
  • JDK8: Application class loader: responsible for loading all class libraries in the classpath path
  • Java programs cannot refer to the boot classLoader directly. Set the ClassLoader to NULL and use the boot classLoader by default
  • Rather than waiting for a class to be “actively used for the first time,” the JVM specification allows the classloader to preload a class when it expects it to be used
  • If the.class file is missing while loading, a LinkageError is reported the first time the class is actively used. If it has never been used, no error is reported

Parental delegate model

  • Classloaders in the JVM typically adopt a parental delegate model, requiring that all classloaders have their own parent loader in addition to starting the ClassLoader. The parent-child relationship here is combination rather than inheritance, and it works as follows:
  1. When a classloader receives a class load request, it first searches for all “named modules” defined by its built-in loader.
  2. If the appropriate module definition is found, it will be loaded using the loader
  3. If the Class is not found in the named module defined by these loaders, it is delegated to the parent loader until the class loader is started
  4. If the parent loader reports that it cannot complete the load request, such as not finding the class in its search path, the subclass loader does the loading itself
  5. Classes found under the classpath become the nameless modules of these loaders
  • The parental delegate model is important to ensure the stable operation of Java programs and to prevent a class from being loaded multiple times
  • The code that implements the parent delegate is in the loadClass() method of the java.lang.ClassLoader, and it is recommended to override the implementation of the findClass() method if you are custom classloaders
  • If there is a Class loader that can load a particular Class, it is called a defining Class loader. All Class loaders that successfully return a Class of that Class are called initial Class loaders

Description of the parental delegate model

  • The parental delegate model is important to ensure the stable operation of Java programs
  • In the loadClass() method of the code java.lang.ClassLoader that implements the parent delegate, it is recommended to override the implementation of the findClass() method if you have a custom ClassLoader
  • If there is a Class loader that can load a particular Class, it is called a defining Class loader, and all Class loaders that successfully return a Class of that Class are called initializer loaders
  • If no parent loader is specified, the default is to start the class loader
  • Each class loader has its own namespace. The namespace consists of the classes loaded by the class loader and all of its parent loaders. Different namespaces may have the same full pathname of the class
  • The runtime package consists of classes in the same classloader, and whether two classes belong to the same runtime package depends not only on whether the full pathname is the same, but also on whether the definition classloader is the same. Only classes that belong to the same runtime package can be made visible within each other’s packages

Corrupt the parental delegate model

  • The problem with the parent delegate model is that the parent loader cannot recognize down the resources loaded by the child loader
  • To solve this problem, a thread-context classloader is introduced, which can be set through the setContextClassLoader() of Thread
  • When implementing hot deployments, such as OSGi’s modular hot deployment, its classloaders are no longer strictly based on the parent delegate model, and much may be executed in the horizontal classloaders

Class connection and initialization

Class to connect to the content of the main validation

  • Class file structure check: Follow the class file structure specified in the JVM specification
  • Metadata validation: Semantic analysis of the information described by bytecode to ensure that it conforms to the Java language specification
  • Bytecode validation: Analyzing the data flow and control flow to ensure that the program semantics are legitimate and logical. Here, the method body is mainly verified
  • Symbol reference validation: Verifies matching of information outside of the class itself, that is, symbols in the constant pool

Class in the connection

  • Allocates memory for a static variable of the class and initializes it

Parsing in a class join

  • Parsing is the process of converting a symbolic reference in a constant to a direct reference, including: symbolic reference: a set of unambiguous (unique) symbols describing the referenced target, irrespective of the virtual machine’s invalidation
  • Direct reference: Pointer, relative offset, or handle that executes the target directly are implementation-specific
  • Mainly for: class, interface, field, class method, interface method, method type, method handle, call point qualifier

Class initialization

  • Class initialization is the assignment of initial values to static variables of the class, or the execution of class constructor methods
  1. When we initialize a class, we don’t initialize the interface it implements first
  2. When an interface is initialized, its parent interface is not initialized first
  3. An interface is initialized only when a program first uses a variable in the interface or when it calls an interface method
  4. If the class is not already loaded and connected, load and connect first
  5. If a class has a parent class, and the parent class is not initialized, the parent class is initialized first
  6. If any initialization statements exist in the class, they are executed in turn
  7. If it is an interface:
  8. The loadClass method class that calls the ClassLoader class loads a class, does not initialize the class, and is not an active use of the class

Active initialization of the class

Class when to initialize

  • Java programs can use classes in either active or passive ways. The JVM must initialize each class or interface when it is “actively used” for the first time. Passive use of a class does not result in class initialization. Active use:
  1. Creating a Class Instance
  2. Accessing a static variable of a class or interface
  3. Invokes static methods of the class
  4. Reflect a Class
  5. Initializes a subclass of a class that has not yet been initialized
  6. The main class that runs when the JVM starts
  7. Define the interface to the default method when the interface implements class initialization

Class of unloading

  • When the Class object representing a Class is no longer referenced, the Class object’s life cycle ends and the corresponding data in the method area is unloaded
  • Classes loaded by the JVM’s own classloader will not be unloaded. Classes loaded by user-defined classloaders can be unloaded

Memory allocation

Insert the picture description here

Simplified architecture and runtime data areas for the JVM

Insert the picture description here

Runtime data area

  • PC register, Java virtual stack, Java heap, method area, run-time constant pool, local method stack, etc

PC register

  • Each thread has a PC register, which is thread private and is used to store the address to the next instruction
  • When a thread is created, the corresponding PC registers are created
  • When executing a local method, the value of the PC register is undefined
  • Is a relatively small area of memory that is the only area of memory where OutOfMemoryErrors are not specified in the JVM specification

Java stack

  • A stack consists of a series of frames (frames) (hence the Java stack is also called a Frame stack) and is thread private
  • Stack frames are used to hold the local variables of a method, the operand stack (Java has no registers and all arguments are passed using the operand stack), constant pool Pointers, dynamic linking, method returns, and so on
  • Each method call creates a frame and presses the stack. When exiting the method, the contents of the stack frame are destroyed by changing the top pointer of the stack
  • The local variable table holds various basic data types and reference types known at compile time. Each slot holds 32 bits of data (long, double, and two slots)
  • Stack advantage: access speed than the heap block, second only to registers
  • Disadvantages of the stack: the size of the data in the stack, the survival zone is determined by the compiler, lack of flexibility

The Java heap

  • Used to hold objects and arrays created by the application system. All threads share the Java heap
  • The GC primarily manages the heap space, and for generational GC, the heap is also generational
  • Heap advantages: runtime dynamic allocation of memory size, automatic garbage collection;
  • Disadvantages of heaps: relatively slow efficiency

Methods area

  • Method areas are shared by threads and are typically used to hold structural information about loaded classes
  • Usually associated with metaspaces, but specific to JVM implementation and version
  • The JVM specification describes the method area as a logical part of the heap, but it has an alias called non-heap, presumably to separate it from the Java heap

Runtime constant pool

  • Is a constant pool table for each Class or interface in a Class file. It is a run-time representation of the Class, usually including: version, field, method, interface, etc
  • Assign in the method area
  • Typically, after the classes and interfaces are loaded into the JVM, the appropriate run-time constant pool is created

Local Method Stack

  • The stack used in the JVM to support native method execution is the native method stack

Stack, heap, method area interaction

Insert the picture description here

Java heap memory model and allocation

An overview of Java heap memory

  • The Java heap is used to hold objects and arrays created by the application system and is shared by all threads
  • The Java heap dynamically allocates the size of memory at run time for garbage collection
  • Java garbage collection (GC) is primarily about reclaiming heap memory, and for generational GC, the heap is also generational

The structure of the Java heap

Insert the picture description here

  • The new generation is used to store newly allocated objects; The objects that are garbage collected in the new generation are copied into the old generation
  • The age of an old storage object is much older than that of a new storage object
  • The old age stores some large objects
  • Total heap size = new generation + old age
  • Cenozoic = Eden + survival zone
  • In the previous generation of persistence, the area used to store meta-information such as Class and Method was removed from JDK8 and replaced by metaspaces (MetasPace), which are not in the virtual machine but directly use local memory

Object memory layout

  • The layout of objects stored in memory (illustrated here by the HotSpot virtual machine) is divided into: object headers, instance data, and aligned population
  • Object header, which contains two parts:
  • Mark Word: Stores the object’s own runtime data, such as hashCode, GC generation age, lock status flags, etc
  • Type pointer: An object’s pointer to its class metadata
  • Instance data: Where the object instance data is actually stored
  • Align padding: This part doesn’t have to exist and has no special meaning. It’s just a placeholder. Because Hotspot requires objects to start at multiples of 8 bytes, if not, align

Object access location

  • Using Handles: There is a block of memory in the Java heap that is used as a pool of handles. The address of the handle is stored in the reference, and the address of the instance data of the object and the class metadata is stored in the handle, as shown in the figure

Insert the picture description here

  • Using Pointers: Java heap stores addresses that access class metadata. Reference stores addresses of objects directly, as shown in the figure below:

Insert the picture description here

Trace tracing and parameter configuration of the Java heap

doc

Trace parameter

  • You can print brief information about the GC: -Xlog: GC
  • Print GC details: -Xlog: GC *
  • Specify the location of the GC log to output as a file: -Xlog: GC :garbage-collection.log
  • After each GC, the heap information is printed: -XLOG: GC + Heap = DEBUG

GC log format

  • The time the GC occurs, which is the number of seconds that the JVM has elapsed since startup
  • Log level information, and log type markers
  • The GC identification number
  • The type of GC and the reason for GC
  • Capacity: pre-GC capacity -> post-GC capacity (the total capacity of the region)
  • Duration of GC in seconds. Some collectors have detailed descriptions, such as user representing the time elapsed by the application, sys representing the time elapsed by the system kernel, and real representing the time from start to finish of an operation

Parameters to the Java heap

  • -xms: initializes heap size, default 1/64 of physical memory
  • -Xmx: Maximum heap size, default 1/4 physical memory
  • -Xmn: Cenozoic size, default 3/8 of the whole heap
  • – XX: + HeapDumpOnOutOfMemoryError: OOM heap exported to a file
  • -XX: +HeapDumpPath: Export OOM path
  • -XX:NewRatio: Ratio of the old to the new. If XMS = XMX and XMN is set, this parameter is not set
  • -XX:SurvivorRatio: The ratio between the size of Eden and that of a Survivor. If set to 8, then the ratio of two Survivor regions to one Eden is 2:8, and one Survivor accounts for 1/10 of all births
  • -XX:OnOutOfMemoryError: Execute a script while in OOM
  • -xss: Usually only a few hundred K, which determines the depth of the function call

Parameter to the meta space

  • -XX: Metaspacesize: Size of the initial space
  • -XX: MaxMetAspacesize: Maximum space, which is unrestricted by default
  • -XX: MinMetaspacefreeRatio: The percentage of space capacity left for the smallest Metaspace after GC
  • -XX: MaxMetaspacefreeRatio: The percentage of the maximum Metaspace space capacity left after GC

Bytecode execution engine

  • The JVM’s bytecode execution engine basically inputs bytecode files, parses and processes the bytecode, and outputs the result of execution
  • This may be done by directly interpreting the bytecode through the interpreter, or by producing native code through the just-in-time compiler, which is called compilation execution, or by both

The stack frame

  • Stack frames are data structures used to support method calls and method execution by the JVM
  • The stack frame is created with the method call and destroyed when the method ends
  • The stack frame stores the method’s local variables, operand stack, dynamic linking, method return address, and other information

Local variation scale

  • Local variable table: Storage space for method parameters and local variables defined within a method
  1. A slot currently holds data types up to 32 bits
  2. 2 slots for 64-bit data
  3. For instance methods, the 0th slot holds this and is then assigned to the parameter list from 1 to n
  4. Slots are then allocated based on the order and scope of variables defined within the method body
  5. Slots are multiplexed to save space on stack frames, a design that can affect the garbage collection behavior of the system

The operand stack

  • The operand stack is used to store data for the operation of each instruction during the execution of a method
  1. The data types of the elements in the operand stack must exactly match the order of the bytecode instructions
  2. The virtual machine may optimize the implementation of stack frames so that there is some overlap between the two stack frames in order to hold common data

Dynamic link

  • Dynamic linking: Each stack frame holds a reference to the method to which the stack frame belongs in the run-time constant pool to support dynamic linking of the method invocation process
  1. Static resolution: Symbolic references are converted to direct references when the class is loaded
  2. Dynamic linking: converted to a direct reference at run time

Method return address

  • Method return address: The address returned after the method is executed

The method call

  • Method invocation: It is the determination of which method to call and does not involve the execution process inside the method
  1. Part of this approach is to establish the direct reference relationship directly during the parsing phase of the class load
  2. However, instance methods, also known as virtual methods, require runtime dynamic dispatch because of multiplicity and polymorphism

The dispatch

  • Static dispatching: All dispatching methods that rely on static types to locate the version of a method execution, such as overloaded methods
  • Dynamic dispatching: A dispatching method that locates the execution version of a method based on the actual type of the runtime, such as overwriting methods
  • Single dispatching and multiple dispatching: it is to think in terms of dispatching. If there is more than one, it is called multiple dispatching. If there is only one, it is called single dispatching

The garbage collection

Overview of Garbage Collection

  • What is garbage: Simply put, memory space in memory that is no longer being used is garbage
  • Garbage collection algorithm:
  • Objects that can be used as GC ROOTS include objects referenced in the virtual stack (Stack Frame Local Variables), objects referenced by static properties of method section classes, objects referenced by constants in the method section, and objects referenced by JNI in the local method stack
  • Hotspot uses a set of data structures called OopMap for accurate GC purposes
  • With the help of oopMap, the JVM can do the GC Roots enumeration very quickly. However, the JVM does not generate an OopMap for each instruction
  • These “specific points” where the oopMap is recorded are called safe points, and GC is not allowed to be paused until the current thread has reached a safe point
  • If object reference relationships do not change in a piece of code and it is safe to start GC anywhere in that area, then that area is called a safe area
  • Advantages: simple failure, high efficiency
  • Cons: Cannot solve the problem of circular references between objects
  • Reference Counting: Adds a reference counter to an object, increasing it by 1 for accesses and subtracting it by 1 for invalidations
  • Root search algorithm (accessibility analysis method) : from the root node (GC Roots) to search down the object node, the search path is called the reference chain. If there is no connectivity between an object and the root, then the object is not available

Garbage Collection Basics

Across generations reference

  • Cross-generational referencing: That is, an object in one generation references an object in another generation
  • Cross-generational referencing hypothesis: Cross-generational referencing is rare compared to contemporaneous referencing
  • Implicit Corollary: Two objects that refer to each other tend to live or die at the same time

The memory set

  • Remembered Set: An abstract data structure used to record a Set of Pointers from an uncollected area to a collected area
  • Word length accuracy: Each record is accurate to one machine word length, which contains cross-generation Pointers
  • Object precision: Each record is accurate to an object with fields that contain cross-generation Pointers
  • Card precision: Each record is accurate to a memory region that contains objects that contain cross-generation Pointers
  • Card Table: It is a specific implementation of memory set, which defines the record accuracy of memory set and the mapping relationship with heap memory, etc
  • Each element of the Card table corresponds to a block of memory of a specific size in its identified memory area, called a Card Page.

Write barriers

  • Write barriers can be thought of as the JVM’s AOP for the action of assigning a value to a reference type field
  • Write barriers are used to maintain the card table state when the object state changes

Steps to determine whether garbage is present

  • The search algorithm is not available
  • See if it is necessary to implement the Finalize method
  • If the object is still unused after two steps, it is garbage

GC type

  • Minorgc/Younggc: Collecting in the Cenozoic
  • MajorGC/OldGC: GC that takes place in the old age, currently only the CMS collector has the behavior of collecting the old age separately
  • MixedGC: Collect the whole new generation and part of the old generation. Currently only the G1 collector has this behavior
  • FullGC: Collects the entire Java heap and method area by GC

Stop-The-World

  • STW is a global pause phenomenon in Java, mostly caused by GC. A global pause is when all Java code stops running, allowing native code to execute but not interact with the JVM
  • Its harm is a long time of service stop, no response; For HA system, it may cause main-standby switch and seriously harm the production environment

Garbage Collection Types

  • Serial collection: GC single-threaded memory collection that pauses all user threads, such as Serial
  • Parallel collection: Multiple GC threads work concurrently while the user thread is paused, e.g., Parallel
  • Concurrent collection: User threads and GC threads execute simultaneously (not necessarily in parallel, but alternately) without pausing the user thread, such as a CMS

A condition to determine that a class is useless

  • All instances of this class in the JVM have been reclaimed
  • The ClassLoader that loaded the class has been reclaimed
  • There is no reference anywhere to the Class object of the Class
  • This class cannot be accessed by reflection anywhere

Garbage collection algorithm

Tag scavenging algorithm

  • Mark-sweep algorithm: It is divided into two stages: Mark and Sweep. The objects to be recycled are marked first, and then the objects are uniformly recycled
  • Insert the picture description here

  • Pros: Simple
  • Disadvantages:
  • It’s not very efficient. It’s not very efficient to mark and clear
  • A large number of discrete memory fragments are generated, causing GC to be triggered when large objects are allocated

Replication algorithm

  • Coping algorithm: Break memory into two identical areas and use one at a time, and when one is used up, you just copy the surviving objects on that one piece into another piece and then get rid of that piece
  • Insert the picture description here

  • Advantages: simple implementation, efficient operation, no need to consider the problem of memory fragmentation
  • Disadvantages: some memory waste
  • In the actual JVM implementation, memory is divided into a larger Eden and two smaller Survivor Spaces. Each time Eden and one Survivor are used, the surviving objects are copied to the other Survivor on recycling
  • Hotspot’s default Eden to Survivor ratio is 8:1, which means it can use 90% of the new generation space at a time
  • If you run out of Survivor space, you will have to rely on the old age to allocate guarantees, and send the objects that can’t fit into the old age directly to the old age

    Assignment guarantee: after the garbage collection of the new generation, the living area of the new generation cannot be placed, so the strategy of placing these objects to the old generation is needed, that is, the old generation provides space allocation guarantee for the GC of the new generation. The steps are as follows:

  1. Before a MinorGC occurs, the JVM checks to see if the maximum available contiguous space of the old age is greater than the total space of all objects in the new generation, and if so, to ensure that the MinorGC is safe
  2. If less, then the JVM checks to see if the allowable guarantee is set to fail, and if it is, it continues to check to see if the maximum available contigous space of the old age is greater than the average size of objects that have been promoted to the old age
  3. If greater than, try a MINORGC
  4. If not, do a Full GC instead

Tag collation algorithm

  • Mark-compact algorithm: because the replication algorithm is inefficient and has a waste of space when there are many living objects, the replication algorithm is generally not used in the old age, and the marking Compact algorithm is mostly used in the old age
  • The tagging process is the same as the tagging purging algorithm, but instead of directly purging the recyclable objects, all surviving objects are moved to one end, and then the memory outside the boundary is directly purged
  • Insert the picture description here

Garbage collector

  • Serial collector, Parallel collector, Parallel generation, Parallel Scavenge collector, CMS, G1
  • Insert the picture description here

Serial collector

  • Serial Collector/Serial Old Collector is a single-threaded collector that stops the World during garbage collection
  • Insert the picture description here

  • Pros: Simple, may be more efficient for a single CPU because there is no multithreaded interaction overhead, is the default Client mode of the next generation of collectors
  • Open with -XX:+UseSerialGC, which uses the collector combination of: Serial + SerialOld
  • The new generation uses the copy algorithm, and the old generation uses the marker-collate algorithm

Parallel collector

ParNew collector

  • Parnew (parallel) collector: uses multiple threads for garbage collection, with stop-the-world during garbage collection
  • Insert the picture description here

  • In a CPU environment with good concurrency capacity, it pauses for less time than the serial collector. But for CPUs with a single CPU or weak concurrency, it may be worse than a serial collector due to the interaction overhead of multiple threads
  • It is the preferred next-generation collector in Server mode and can be used in conjunction with the CMS collector
  • No longer use -XX:+ UseParnewGC to open it separately
  • -XX:ParallelGCThreads: Specifies the number of threads, preferably the same as the number of CPUs

The new generation Parallel Scavenge collector

  • Parallel Scavenge collector: Parallel Scavenge collector is a Parallel Scavenge collector for the new generation that uses a replication algorithm
  • Similar to Parnew, but more focused on throughput, maximum efficient CPU use, and suitable for running background applications
  • Insert the picture description here

  • Use -XX:+UseParallelGC to turn this on
  • Use -XX:+ UseParalleloldGC to enable the ParallelOld collector. Use a combination of Parallel Scavenge + ParallelOld collector
  • -XX: MAXGCPauseMillis: Sets the maximum pause time for GC
  • The new generation uses the copy algorithm, and the old generation uses the marker-collate algorithm

CMS collector

  • The CMS (Concurrent Mark and Sweep Concurrent Mark Sweep) collector is divided into: initial Mark: Mark only the objects that GC Roots can directly relate to; Concurrent Labeling: Perform GC Roots Tracing
  • Relabeling: The part of an object whose markup has changed as a result of the program running during the correction of concurrent markup
  • Concurrent Cleanup: Garbage objects are collected concurrently
  • Insert the picture description here

  • Stop-the-world will still occur during the initialization mark and relagging phases
  • Using the tag scavenging algorithm, the garbage collector is concurrently collected by multiple threads
  • The final reset thread, which clears the data associated with the collection and resets it in preparation for the next collection
  • Advantages: low pause, concurrent execution
  • Disadvantages:
  • Concurrent execution, large pressure on CPU resources
  • Unable to handle garbage generated during processing (floating garbage), which may result in FULLGC
  • The tag removal algorithm used causes a large amount of fragmentation, which may trigger FULLGC when allocating large objects
  • Open: -XX: UseConcMarksweepGC: use the collector combination ParNew + CMS + Serial Old, Serial Old will act as a backup collector for CMS failures
  • CMS collector – XX: CMSInitiatingOccupancyFraction: set how much space is used on the old s triggered after the recovery, 80% by default

G1 collector

  • G1 (Garbage-First) collector: The G1 (Garbage-First) collector is a collector for service-oriented applications that, compared to other collectors, has the following characteristics:
  1. G1 divides memory into independent regions
  2. G1 still adopts the idea of generation, keeping the new generation and the old age, but they are no longer physically isolated, but the set of a part of Region, and the Region does not need to be continuous
  • Insert the picture description here

  • G1 can make full use of multi-CPU, multi-core environment hardware advantages, as far as possible to shorten STW
  • G1 adopts mark-collate algorithm on the whole, and copy algorithm locally, without memory fragmentation
  • G1 pauses are predictable and explicitly specify how much time cannot be spent on garbage collection in a given period of time
  • G1 tracks the value of the garbage heap in each Region, maintains a priority list in the background, and recycles the Region with the largest value according to the allowed time each time, so as to ensure efficient collection in a limited time
  • Garbage collection:
  • Initial markup: Marks only the objects that GC ROOTS can relate directly to
  • Concurrent Labeling: Perform GC Roots Tracing
  • Final markup: The part of the object whose markup has changed as a result of the program running during the correction of concurrent markup
  • Filter Recovery: Value maximizing recovery based on time
  • Insert the picture description here

  • Use and configure G1: -XX:+UseG1GC: Enable G1, default is G1
  • -XX: MAXGCPauseMillis = N: Maximum GC pause time, which is a soft target and the JVM will try (but not guarantee) to pause less than this time
  • – XX: InitiatingHeapOccupancyPercent = n: the number of triggered when the GC heap usage, the default is 45
  • -XX:NewRatio = N: Default is 2
  • -XX:SurvivorRatio = n: Default is 8
  • -XX:MaxTenuringThreshold = n: Age from Cenozoic to Old, the default is 15
  • -XX:ParallelGCThreads = n: The number of parallel GC threads, the default value will vary depending on the platform
  • -XX: ConcgCThreads = n: The number of threads used by the concurrent GC
  • -XX:G1ReservePercent = n: Sets the percentage of memory reserved as free space to reduce the risk of target space overflow. The default is 10%
  • -XX:G1HeapRegionSize = n: Size of G1 region set. The value is a power of 2, with a range of 1MB to 32MB, and the goal is to partition about 2048 regions based on the minimum Java heap size

ZGC Collector (Understand)

  • ZGC collector: An experimental low-latency collector added to JDK11
  • The ZGC is designed to support terabyte memory capacity, low pause times (<10ms), and less than 15% of overall program throughput
  • New technology in ZGC: Shader Pointer and Read Barrier
  • GC Performance Indicators:
  • Throughput = time spent executing the application code/total time spent running
  • The GC load, as opposed to throughput, is the total GC time/run time
  • The pause time is the total time that the stop-the-world occurred
  • GC frequency is the number of times GC occurs in a period of time
  • Reaction speed: is the time from the object becomes garbage to be recycled
  • Interactive applications usually want as little pause time as possible
  • JVM memory configuration principles:
  • Set the new generation as large as possible. If it is too small, it will cause:
  • For older applications, response time priority: Since older applications typically use concurrent collectors, the size should take into account parameters such as the amount of concurrency and the duration of concurrency
  • For old age, throughput first applications: usually set the large new generation and the small old age so that you can recover as much of the short term objects as possible, reduce the medium term objects, and the old age to hold the long lived objects as possible
  • The objects are classified according to their life cycle. The objects are allocated in the new generation first, and the objects that survive for a long time enter the old age
  • According to the characteristics of different generations, select the appropriate collection algorithm: a small number of objects survive, suitable for replication algorithm; A large number of objects live, suitable for tag purging or tag collation
  1. If the setting is too small, it can cause memory fragmentation, and high collection rates can cause the application to pause
  2. If the setting is too large, the collection time will be longer
  3. YGC is more frequent
  4. May cause objects after YGC to enter the old age, and trigger FGC if the old age is full at this point

Efficient concurrent

The Java Memory Model and Interactions Between Memory

Java Memory Model

  • The JCP defines a Java memory model that was previously part of the JVM specification but later became a standalone version of JSR-133(Java Memory Model and Threading Specification Revision).
  • Memory model: An abstraction of the process of reading and writing access to a particular memory or cache under a particular operating protocol
  • The Java memory model focuses on the underlying details of storing variable values into memory and retrieving them from memory within the JVM
  • Insert the picture description here

  • All variables (shared) are stored in main memory, and each thread has its own working memory; The working memory holds a copy of the main memory copy of the variable used by the thread
  • All operations (read, write) on variables by threads should be completed in working memory
  • Different threads cannot access each other’s working memory. Interacted data passes through main memory

Interactions between memory

  • The Java Memory Model specifies operations for memory-to-memory interactions that the JVM will preserve as atomic
  • Lock: Identifies the variable as thread-exclusive and applies to the main memory variable
  • Unlock: To release a variable that is locked so that it can only be used by another thread
  • Read: Read a variable from main memory into working memory
  • Load: loads the value read into a copy of the variable in working memory
  • Use: To pass the value of a variable in working memory to the execution engine
  • Assign: Assign the value received from the execution engine to a variable in working memory
  • Store: To pass the value of a variable in working memory to main memory
  • Wirte: Writes the data from store into variables such as main memory
  • Insert the picture description here

Rules for the interaction between memory

  • One of the read and load, store and write operations is not allowed to occur in isolation. The above two operations must be executed in sequence, but there is no guarantee of sequential execution. In other words, other instructions can be inserted between read and load and between store and write
  • A thread is not allowed to discard its recent assign operation, which means that a variable that has changed in working memory must synchronize the change back to main memory
  • A thread is not allowed to synchronize data from the thread’s working memory back to main memory for no reason (no Assign operation has ever occurred)
  • A new variable can only be “born” from main memory. It is not allowed to use an uninitialized variable in working memory. In other words, you must perform the assign and load operations on a variable before you can use and store it
  • A variable can only be locked by one thread at a time, but a lock operation can be repeated by the same thread several times. After a lock has been executed several times, the variable will only be unlocked by executing an unlock operation the same number of times
  • If a lock operation is performed on a variable, the value of the variable in working memory will be cleared. Before the execution engine can use the variable, it needs to re-execute the load or assign operation to initialize the value of the variable
  • If a variable is not locked by a lock operation, you are not allowed to unlock it, nor can you unlock a variable that has been locked by another thread
  • Before an unlock operation can be performed on a variable, it must be synchronized back into main memory (store and write operations)

Volatile features

Visibility in multithreading

  • Visibility: When one thread modifies a variable, other threads know about it
  • Common ways to ensure visibility: volatile, synchronized, final (visible to other threads once initialized)

volatile

  • Volatile is basically the lightest synchronization mechanism available to the JVM. A variable marked with volatile is visible to all threads, meaning that a write to a volatile variable is immediately reflected in other threads
  • Variables that are volatile are still unsafe in a multithreaded environment
  • Variables that are volatile are disallowed for instruction reorder optimization
  • Suitable for Valatile scenarios
  • The result of the operation does not depend on the current value of the variable
  • Make sure that only one thread modifies the value of the variable

Instruction rearrangement

  • Instruction rearrangement: It is a process in which the JVM, for optimization purposes, rearranges the instructions to a certain extent, if the conditions permit, so as to directly run the subsequent instructions that can be executed immediately, avoiding the waiting time caused by obtaining the data needed for the next instruction
  • Serial semantics within threads, regardless of semantics between multiple threads
  • Not all commands can be reordered. For example:
  • A = 1; B = a; After you write a variable, read the position
  • So let’s say a = 1; A = 2; After you write a variable, you write that variable
  • After reading, write A = B; B = 1; After you read a variable, you write that variable
  • A = 1; A = 1; B = 2; It can be rearranged
  • Principle of Program Sequence: Guarantee semantic serialization within a thread
  • Volatile rule: Writes of volatile variables occur before reads
  • Lock rule: Unlock must occur before the subsequent lock
  • Transitivity: A precedes B, and B precedes C, so A must precede C
  • The thread’s start method precedes each of its actions
  • All operations of a thread precede the end of the thread
  • Thread interrupt() code that precedes the interrupted thread
  • The constructor execution of the object ends before the finalize() method

Java thread-safe handling

  • Immutability is thread safe
  • The mutex synchronization (non-blocking synchronous) : synchronized, Java. Util. Concurrent. Already. Synchronized is recommended as the preferred option for both methods. ReentrantLock adds the following features:
  • Wait interruptible: When the thread holding the lock does not release the lock for a long time, the waiting thread can choose to abort waiting
  • Fair lock: When multiple threads are waiting for the same lock, the lock must be acquired in strict time order in which the lock is applied
  • Locks bind to multiple conditions: A ReentrantLock object can bind to multiple conditions, while synchronized binds to a single condition, requiring multiple locks
  • Non-blocking synchronization is an optimistic locking strategy based on conflict checking. It is usually operated first, if there is no conflict, the operation is successful, and if there is a conflict, the operation can be compensated in other ways
  • No synchronization: In multithreaded situations, methods do not involve sharing data, and therefore no synchronization is required

Lock the optimization

Spin lock and adaptive spin

  • Spin: If a thread can acquire a lock quickly, instead of the OS layer suspending the thread, it can make several busy loops. This is called spin
  • Adaptive spin: the spin time is no longer fixed, but is determined by the previous spin time on the same lock and the state of the lock owner
  • If the lock is held for a short time and the spin is successful, you can improve system performance by saving thread hangs and switching time
  • If the lock is held for a long time and the spin fails, it can waste processor resources and degrade system performance

Lock elimination

  • When the code is compiled, it is detected that there is no shared data race at all, so the synchronization lock is not required. Open with -XX:+EliminateLocks
  • Escape analysis will also be enabled using -XX: DoesCapeAnalysis

    Escape analysis:

  1. If an object defined in a method can be referenced by an external method, it is called a method escape
  2. If the object may be accessed by another external thread, it is called a thread escape, such as an assignment to a class variable or an instance variable that can be accessed from another thread

Lock coarsening

  • In general, synchronization blocks are required to be small, but a series of sequential operations that cause an object to be repeatedly locked and unlocked can lead to unnecessary performance costs. In this case, it is recommended to extend the scope of lock synchronization to the entire sequence of operations

Lightweight lock

  • Lightweight is compared to the traditional lock mechanism, the original intention is to reduce the traditional lock mechanism using OS to achieve mutual exclusion in the case of no multi-thread competition caused by performance loss
  • Its implementation principle is very simple, is similar to the optimistic lock way
  • If the lightweight lock fails, it indicates that there is a race, escalating to a heavyweight lock, resulting in performance degradation

Biased locking

  • Biased locking eliminates synchronization in the case of no contention, even optimistic locking is not used, thus improving performance. The bias is bias, where the lock is biased in favor of the thread that currently owns the lock
  • As long as there is no contention, the thread that acquired the biased lock does not need to synchronize in the future when it enters the synchronized block
  • The bias mode ends when another thread requests the same lock
  • If most of the locks in the program are accessed by multiple threads all the time, which means there is a lot of competition, biased locking can actually degrade performance
  • Use -XX: -usebiasedlocking to disable biased locking, which is turned on by default

Steps to acquire a lock in the JVM

  • Will try biased locking first; Then try a lightweight lock
  • Then try the spin lock
  • Finally, try the normal lock, which is suspended at the operating system layer using the OS mutex

Basic rules for synchronizing code

  • Minimize the time you hold the lock
  • Minimize lock granularity

Performance monitoring and troubleshooting tools

Command line tool

  • Command line tools: JPS, jinfo, jstack, jmap, jstat, jstatd, JCMD
  • Graphics tools: JConsole, JMC, VisualVM
  • Two connection modes: JMX, JSTATD

The role of JVM instrumentation tools

  • Monitor the internal situation of the JVM during operation, such as the view of the JVM parameters, CPU, memory, heap and other information
  • Assist in performance tuning
  • Helps solve application runtime problems such as OutOfMemoryErrors, memory leaks, thread deadlocks, lock contention, Java processes using too much CPU, and so on

jps

  • JPS [options] [hostid] JPS [options] [hostid] JPS [options] [hostid]
  • [protocol:] [[/ /] hostname] [:port] [/ serverName]. If you do not specify a hostid, the default is the current host or server

jinfo

  • Prints configuration information for a given process or core or remote debug server. Syntax format: jinfo [option] pid # Specifies the process number (pid) of the process
  • Jinfo [option]
  • Jinfo [option] [server-id@] # Specifies the remote debug server

jstack

  • Jstack is primarily used to view thread stack information within a Java process. The syntax format is jstack [option] pid
  • jstack [option] executable core
  • jstack [option] [server-id@] remorte-hostname-or-ip

jmap

  • Jmap is used to view heap memory usage in the following syntax format: jmap [option] pid
  • jmap [option] executable core
  • jmap [option] [server-id@] remote-hostname-or-ip

jstat

  • JVM statistics monitoring tools to see the memory and GC conditions of various regions
  • Syntax format is as follows: jstat [generalOption | outputOptions vmid [interval [s | ms] [count]]]

jstated

  • The virtual machine’s jstat daemon is used to monitor the creation and termination of the JVM and provides an interface to order remote monitoring tools attached to the JVM running on the local system.
  • Syntax format: jstatd [options]

jcmd

  • A JVM diagnostic tool that sends diagnostic command requests to a running Java virtual machine. For example, it can be used to export heap, view Java processes, export thread information, perform GC, etc

Graphic chemical tool

jconsole

  • A JMX-compliant graphical tool for monitoring Java virtual machines. It can monitor local and remote JVMs, as well as monitor and manage applications

jmc

  • The Java Mission Control (JMC) client includes tools for monitoring and managing Java applications, rather than introducing the performance overhead typically associated with these types of tools

VisualVM

  • A graphical tool that provides detailed information about Java technology-based applications running in the Java Virtual Machine
  • Java VisualVM provides memory and CPU analysis, heap dump analysis, memory leak detection, access to MBeans and garbage collection

The remote connection

  • JMX connections can be viewed for system-level information such as system information, CPU usage, number of threads, manual garbage collection, etc
  • Jstatd connection mode can provide: the JVM memory distribution details, garbage collection distribution, thread details, you can even see an object using memory size s | ms] [count]]]