💡 Learning without thinking is worthless, thinking without learning is perilous. - Confucius
👉 WeChat public account has been opened, Cai Nong said , students who didn't pay attention remember to pay attention!
This article brings "In-depth Understanding of Java Virtual Machine: JVM Advanced Features and Best Practices" written by Mr. Zhou Zhiming, which is very hard-core!
The book is divided into 5 parts, around the core topics of memory management , execution subsystems , program compilation and optimization , efficient concurrency and other core topics to conduct a comprehensive and in-depth analysis of the JVM, profoundly revealed the working principle of the JVM.
The whole book consists of 5 parts, thirteen chapters, and a total of 358,929 words. The overall structure is quite clear, so that when writing reading notes, it is impossible to excerpt (even want to repeat the whole book), the following is the content of the second part of the whole book, I hope readers can taste it carefully!
1. The first part walks into Java
The first part introduces the technical system and development history of Java, and talks about the future. This part of the content is not excerpted, and directly enters the core theme.
Second, the second part of the automatic memory management mechanism
Between Java and C++, there is a "high wall" surrounded by dynamic memory allocation and garbage collection technology. People outside the wall want to go in, but people inside the wall want to come out.
Chapter 2 Java memory area and memory overflow exception
It is both happy and sad for Java programmers. With the help of the automatic memory management mechanism of the virtual machine, it is not necessary to write paired delete/free code for each new operation, and it is not easy to have memory leaks and memory overflow problems, but In the field of memory management, C or C++ is both the "emperor" with the highest power and the "working people" who are engaged in the most basic work.
1) Runtime data area
In the process of executing Java programs, the Java virtual machine divides the memory it manages into several different data areas.
program counter
This is a small piece of memory that can be seen as a line number indicator of the bytecode being executed by the current thread
In order to restore the correct execution position after thread switching, each thread needs to have an independent program counter, the counters between each thread do not affect each other, independent storage, thread private .
This memory region is the only region that does not specify any OutOfMemoryError conditions in the Java Virtual Machine Specification.
1. Virtual machine stack
Like the program counter, the Java virtual machine stack is also thread-private and has the same life cycle as a thread. The virtual machine describes the memory model of Java method execution: each method will create a stack frame to store local variable table, operand stack, dynamic link, method exit and other information when executing. The process of each method from invocation to completion of execution corresponds to the process of a stack frame being pushed to the stack in the virtual machine stack.
2. Native method stack
It is very similar to the virtual machine stack, the main difference is that the virtual machine stack is for the virtual machine to execute the Java method service, and the local method stack is for the native method used by the virtual machine.
The same as the virtual machine stack: the native method stack also throws StackOverFlowError and OutOfMemoryError exceptions
3. Java heap
The Java heap is the largest piece of memory managed by the Java Virtual Machine. The Java heap is a memory area shared by all threads, created when the virtual machine starts.
The only purpose of this memory area is to store object instances, and almost all object instances are allocated here.
The Java heap is the main area managed by the garbage collector, so it is often called the GC heap, so it can also be subdivided into: the new generation and the old generation, and the new generation can be detailed into Eden space , From Survivor space , To Survivor space , etc.
4. Method area
Like the Java heap, the method area is a memory area shared by each thread, which is used to store data such as class information, constants, static variables, and code compiled by the real-time compiler that have been loaded by the virtual machine.
Permanent generation and method area are not equivalent in essence
The HotSpot virtual machine design team will use the permanent generation to implement the method area, so that the HotSpot garbage collector can manage this part of the memory like the Java heap, which can save the work of writing memory management code for the method area.
The Java virtual machine specification has very loose restrictions on the method area, except that it does not require contiguous memory like the Java heap and can choose a fixed size, and you can also choose not to implement garbage collection.
It is not that the data enters the method area and exists "permanently" as the name of the permanent generation. The memory reclamation target in this area is mainly aimed at the reclamation of the constant pool and the unloading of types. Generally speaking, the recovery "score" of this area is relatively unsatisfactory, especially the unloading of types, the conditions are quite harsh, but this part of the area recycling is indeed necessary
2) Extended description
runtime constant pool
Runtime constants are part of the method area. It is used to store various literals and symbolic references generated during compilation. This part of the memory will be stored in the runtime constant pool that enters the method area after the class is loaded.
Another important feature of the runtime constant pool relative to the Class file constant pool is that it is dynamic (it is not required that constants must be generated only at compile time, and new constants can also be stored in the pool during runtime)
The runtime constant pool is part of the method area , and an OutOfMemoryError exception will be thrown when the constant pool can no longer apply for memory.
direct memory
Direct memory is not part of the virtual machine's runtime data area, nor is it a memory area defined in the Java Virtual Machine specification, but it also causes OutOfMemoryError exceptions.
NIO, introduced in Java 1.4, is an I/O method based on Channel and Buffer. Native function library can be used to directly allocate off-heap memory , avoiding copying back and forth between Java heap and Native heap. data, which can significantly improve performance in some scenarios.
Allocation of direct memory is not limited by the Java heap size, but is still limited by the total native memory size and processor addressing space.
3) HotSpot virtual machine object exploration
object creation
As we all know, the creation of objects is usually generated using the new keyword
When the virtual machine encounters a new instruction, it will first check whether the parameters of this instruction can locate a symbolic reference of a class in the constant pool, and check whether the symbolic reference has been loaded , resolved and initialized (the process of class loading). If not, the corresponding class loading process must be performed first.
After the class loading check is passed, the virtual machine will allocate memory for the new object. The size of the memory required by the object can be completely determined after the class loading is completed. The task of allocating space for the object is equivalent to removing a block of memory of a certain size from the Java heap. divided out.
Allocating memory is simply moving the pointer to the free space by a distance equal to the size of the object. This allocation method is called pointer collision. (The virtual machine must maintain a list to record which memory blocks are available, and find a large enough space from the list to divide it into the object instance when it is allocated. This allocation method is called a free list )
Of course, concurrency issues need to be considered when creating objects. It is possible to allocate memory to object A, but the pointer has not had time to be modified, and object B uses the original pointer to allocate memory at the same time.
There are two solutions to this problem:
- Synchronize the action of allocating memory space - in fact, the virtual machine uses CAS coupled with failed retry to ensure the atomicity of update operations
- The action of memory allocation is divided into different spaces according to threads, that is, each thread pre-allocates a small piece of memory in the Java heap, which is called the local thread allocation buffer (TLAB).
After the memory is allocated, the virtual machine needs to initialize the allocated memory space to zero (excluding the object header). If TLAB is used, this process can also be carried out in advance when the TLAB is allocated.
At this point, a new object is created, but since the <init> method has not been executed, all fields of the object are 0 at this time.
Object's memory layout
The layout stored in the object memory can be divided into three areas: object header (Header), instance data (Instance Data) and alignment padding (Padding)
Object header:
- Used to store the runtime data of the object itself, such as hash code, GC generation age, lock status flags, locks held by threads, biased thread IDs, biased timestamps, etc. The length of this part of the data is 32-bit and 64-bit In the virtual machine (without opening the compressed pointer), it is 32 bit and 64 bit respectively, officially called Mark Word.
- The other part is the type pointer, that is, the pointer to the object's class metadata, and the virtual machine uses this pointer to determine which class the object is an instance of.
Example data:
It is the effective information that the object actually stores, and it is also the field content of various types defined in the program code. Whether it is inherited from the parent class or defined in the subclass, it needs to be recorded. This part of the storage order is affected by the order in which the virtual machine allocation strategy parameters and fields are defined in the Java source code.
Align padding:
This part does not necessarily exist, nor does it have a special meaning, it just acts as a placeholder.
object access location
Objects are created in order to use objects. Our Java programs need to manipulate specific objects on the heap through the reference data on the stack.
At present, there are two mainstream object access methods.
- handle access. A piece of memory will be divided into the handle pool in the Java heap, and the handle address of the object is stored in the reference, and the handle contains the specific address information of the object instance data and type data.
- Direct pointer access. The layout of the Java heap object must consider how to place the relevant information of the access type data, and the object address is stored in the reference.
Both of these object access methods have their own advantages:
- Handle access: The most stable handle address stored in the reference. When the object is moved (moving objects is a very common behavior during garbage collection), only the instance data pointer in the handle is changed, and the reference itself does not need to be changed.
- Direct pointer access: faster, saves the time overhead of a pointer positioning
4) OutOfMemoryError exception
In addition to the program counter, several other runtime areas have the potential for OOM exceptions.
heap memory overflow
The Java heap is used to store object instances. As long as objects are continuously created and there is a reachable path between GC Roots and objects to avoid garbage collection mechanism to clear these objects, memory will be generated when the number of objects reaches the maximum heap capacity limit. Overflow exception.
For a specific analysis of the specific situation, you can use a memory image analysis tool (such as Eclipse Memory Analyzer) to analyze the heap dump snapshot from Dump. The key is to confirm whether the object in the memory is necessary, that is, it is necessary to first distinguish whether it has appeared. Memory Leak or Memory Overflow
If it is a memory leak, then it is necessary to find out how the leaked objects are associated with GC Roots and prevent the garbage collector from automatically collecting them.
If it is a memory overflow, you need to check the heap parameters (-Xms and -Xmx) of the virtual machine, compare it with the physical memory of the machine to see if it can be increased, and check from the code whether there are some objects whose life cycle is too long, If the state time is too long, try to reduce the memory consumption of the program runtime.
Virtual machine stack and native method stack overflow
- If the stack depth requested by the thread is greater than the maximum depth allowed by the virtual machine, a StackOverflowError exception will be thrown
- If the virtual machine cannot apply for enough memory space when expanding the stack, an OutOfMemoryError exception is thrown
Method area and runtime constant pool overflow
When the constant pool overflows at runtime, the prompt information that follows the OutOfMemoryError is PermGen space.
Method area overflow is also a common memory overflow exception. For a class to be reclaimed by the garbage collector, the judgment conditions are relatively harsh.
In applications that often generate a large number of classes dynamically, special attention should be paid to the recycling status of classes.
In addition to the use of CGLib bytecode enhancements and dynamic languages, such scenarios are common: a large number of JSPs or applications that dynamically generate JSP files.
Use (JSP needs to be compiled into Java classes when running for the first time), OSGi-based applications (even the same class file is used by different loaders
loading is also treated as a different class) etc.
Native direct memory overflow
DirectMemory capacity can be specified by -XX: MaxDirectMemorySize
. If not specified, the default is the same as the Java heap maximum (-Xmx).
A memory overflow exception is also thrown when DirectByteBuffer allocates memory, but when it throws an exception, it does not really apply to the operating system to allocate memory, but learns from the computer that the memory cannot be allocated, so it throws an exception manually to really apply for memory allocation. The method is: unsafe.allocateMemory()
An obvious feature of memory overflow caused by DirectMemory is that no obvious exceptions will be seen in the Heap Dump file. If the reader finds that the Dump file after OOM is very small, and the program uses NIO directly or indirectly, it can be considered. Check if this is the problem
Chapter 3 Garbage Collector and Memory Allocation Strategy
1) Is the subject dead?
Before the garbage collector can work, it needs to determine which of these objects are alive and which are dead
reference counting
Definition: Add a reference counter to each object. Whenever there is a place to refer to it, the counter value is incremented by 1; when the reference expires, the counter value is decremented by 1; an object whose counter is 0 at any time is impossible to use anymore of.
Defect: Two useless objects refer to each other and cannot be recycled.
accessibility analysis
Definition: Through a series of objects called GC Roots as the starting point, the search starts from these nodes, and the path traversed by the search is called the reference chain . When an object is not connected to the GC Roots by any reference chain, it is proved that this Object is not available.
Available as a GC Roots object:
- Objects referenced in the virtual machine stack (local variable table in the stack frame)
- The object referenced by the class static property of the method area
- The object referenced by the constant in the method area
- Objects referenced by JNI (Native methods) in the native method stack
Kind of citation
After JDK 1.2, Java has expanded the concept of reference, and divided the reference into four types: strong reference, soft reference, weak reference, and virtual reference
- Strong reference: a ubiquitous reference (through the new method), as long as the strong reference still exists, the garbage collector will never reclaim the referenced object
- Soft References: Objects that are still useful but not necessary. Before a memory overflow exception occurs in the system, these objects will be listed in the recycling range for a second recycling. If there is not enough memory for this recycling, a memory overflow exception will be thrown.
- Weak reference: The strength is weaker than the soft reference, and the object associated with the weak reference can only survive until the next garbage collection occurs. When the garbage collector works, objects that are only associated with weak references will be reclaimed regardless of whether the current memory is sufficient or not.
- Virtual reference: Whether an object has a virtual reference will not affect its lifetime at all, and it is impossible to obtain an object instance through a virtual reference. The only purpose of setting a virtual reference association for an object is to receive a system notification when the object is reclaimed by the collector
live or die
Even objects that are unreachable in reachability analysis algorithms are not necessarily dead
When an object is declared dead, it must go through at least two marking processes: if the object is found to have no reference chain connected to GC Roots after reachability analysis, it will be marked for the first time and screened once. The screening conditions Is it necessary for this object to execute the finalize()
method, when the object does not cover the finalize()
method, or has been called by the virtual machine, the virtual machine regards both cases as unnecessary to execute .
If the object is determined to be necessary to execute the finalize()
method, then the object will be placed in a queue called F-Queue and later automatically created by a virtual machine, a low-priority Finalizer thread to execute it.
The finalize() method is the last chance for the object to escape the fate of death. Later, the GC will mark the object in the F-Queue for a second small scale. If the object wants to successfully save itself in finalize() - just reconnect with the You can establish an association with any object on the reference chain. For example, if you assign yourself (this keyword) to a class variable or a member variable of an object, it will be removed from the "about to be recycled" when it is marked for the second time. gather.
Note: The finalize() method of any object will only be called automatically once by the system. If the object faces the next collection, its finalize() method will not be executed again.
Recycling method area
The requirements for the method area in the Java virtual machine specification are relatively loose, and the virtual machine may not be required to implement garbage collection in the method area, but it does not mean that the method area has no garbage collection.
Permanent generation garbage collection mainly recycles two parts: discarded constants and useless classes.
A class needs to meet the following three conditions at the same time to be considered a useless class:
- All instances of the class have been reclaimed, i.e. there are no instances of the class in the Java heap
- The ClassLoader that loaded the class has been recycled
- The java.lang.Class object corresponding to the class is not referenced anywhere, no matter where the methods of the class are accessed through reflection
2) Garbage collection algorithm
mark-sweep algorithm
The mark-sweep algorithm is the most basic collection algorithm. The algorithm is divided into two phases: marking and clearing .
Weaknesses: Efficiency Issues and Space Issues
replication algorithm
The algorithm divides the available memory into two equal-sized blocks according to their capacity. Only one of them is used at a time. When the memory of one block is used up, the surviving objects are copied to the other block, and then the used memory space is used. Clean up once.
Disadvantages: The memory is reduced to half of the original, the price is a bit high
Commercial virtual machines now use this collection algorithm to recycle the young generation. Divide the memory into a larger Eden space and two smaller Survivor spaces. When recycling, copy the surviving objects in Eden and Survivor to another Survivor space at one time, and finally clear Eden and the Survivor space just used. (The default size ratio of Eden and Survivor is 8:1)
mark-collate algorithm
The algorithm is divided into marking and sorting algorithms. The marking process is still the same as the marking-cleaning algorithm, but the subsequent steps are not to clean up the recyclable objects directly, but to move all surviving objects to one end, and then directly clean up beyond the end boundary of memory.
Generational Collection Algorithm
In the new generation, a large number of objects are found to die during each garbage collection, and only a few survive, so the replication algorithm is used, and the collection can be completed with only a small cost of copying the surviving objects. In the old age, because the object's survival rate is high and there is no extra space to allocate it, the "mark-clean" or "mark-clean" algorithm must be used for recycling.
3) Algorithm implementation of HotSpot
enumerate root nodes
The sensitivity of reachability analysis to execution time is also reflected in GC pauses, since this analysis must be done in a snapshot that ensures consistency
Ongoing - "Consistent" here means that the entire execution system appears to be frozen at some point in time throughout the analysis, not
It may happen that the object reference relationship is still changing during the analysis process. If this point is not satisfied, the accuracy of the analysis result cannot be guaranteed.
certificate. This is another reason why all Java threads of execution must be stopped while a GC is in progress (Sun refers to this as " Stop The World ").
An important reason is that even in CMS collectors that claim to be (almost) quiesced, quiescing is necessary when enumerating root nodes.
The virtual machine should have a way to directly know where object references are stored. In the implementation of HotSpot, a group called OopMap is used
data structure for this purpose.
Safe point
With the assistance of OopMap, HotSpot can quickly and accurately complete the GC Roots enumeration, but if the corresponding
OopMap, that will require a lot of extra space, so the space cost of GC will become high.
Therefore, HotSpot will record this information at specific locations , which are called safe points . When the program is executed, it is not possible to stop and start GC in all places. It can only be suspended when it reaches a safe point.
The selection of the safe point is basically based on whether or not it has the characteristics of allowing the program to execute for a long time.
The most obvious feature of long-term execution is the multiplexing of instruction sequences (method calls, loop jumps, exception jumps, etc.)
There are two ways to make all threads run to a safe point and then stop when GC occurs:
- Preemptive interruption: The execution code of the thread does not need to actively cooperate. When the GC occurs, all threads are interrupted first. If it is found that the place where the thread is interrupted is not at the safe point, the thread is restored and let it run to the safe point.
- Active interrupt: When the GC needs to interrupt a thread, it does not directly operate on the thread, but simply sets a flag. When each thread executes, it actively polls this flag, and when it finds that the interrupt flag is true, it interrupts and suspends itself.
safe area
The safepoint mechanism ensures that when the program is executed, it will encounter a Safepoint that can enter the GC in a short period of time.
However, when the program is not executing (thread Sleep or Blocked state), the thread cannot respond to the interrupt request of the JVM. At this time, a safe area is needed to solve it. The safe area is an extended Safepoint.
When the thread executes the code in the Safe Region, it first identifies that it has entered the Safe Region. In this way, when the JVM wants to initiate GC during this period, it does not need to care about the thread that identifies itself as the Safe Region state. When the thread is about to leave When it is in a Safe Region, it checks whether the system has completed the root node enumeration (or the entire GC process), if so, the thread continues to execute, otherwise it must wait until it receives a signal that it is safe to leave the SafeRegion.
4) Garbage collector
If the collection algorithm is the methodology of memory recycling, then the garbage collector is the specific implementation of memory recycling.
Two concepts:
- Parallel (Parallel): refers to multiple garbage collection threads working in parallel, at this time the user thread is still in the waiting state
- Concurrent: The user thread and the garbage collection thread execute at the same time (not necessarily in parallel, but also alternately), the user program continues to run, while the garbage collector runs on another CPU
There are generally collectors that act on different generations in HotSpot. If there is a connection between the two collectors, it can be used together.
Serial collector
This collector is a single-threaded collector, and during garbage collection, all other worker threads must be suspended until it finishes collecting.
ParNew collector
This collector is a multithreaded version of the Serial collector (that is, the behavior is the same as the Serial collector except that multiple threads are processed together). With the exception of the Serial collector, only ParNew can be used with the CMS .
Parallel Scavenge Collector
The collector also uses a replication algorithm. This collector has a different focus than other collectors - the throughput-first collector .
- The focus of collectors such as CMS is to minimize the pause time of user threads during garbage collection as much as possible
- Parallel Scanvenge tries to achieve a controllable throughput (throughput = running user code time / (running user code time + garbage collection time)
The Parallel Scavenge collector cannot work with the CMS collector. If the new generation chooses the Parallel Scavenge collector, the old generation can only choose the Serial Old collector
Serial Old Collector
Serial Old is the older version of the Serial collector, which is also a single-threaded collector and uses a "mark-collate" algorithm.
Parallel Old Collector
Parallel Old is an older version of the Parallel Scavenge collector, using multithreading and a "mark-and-sort" algorithm
CMS collector
The CMS (Concurrent Mark Sweep) collector is a collector whose goal is to obtain the shortest collection pause time.
The CMS collector is based on the "mark-sweep" algorithm. Its operation process is more complicated than the previous collectors. The whole process is divided into 4 steps, including:
- Initial Mark (requires Stop The World)
- concurrent marking
- Relabel (requires Stop The World)
- Concurrent clearing
Since the concurrent marking and concurrent clearing process, which takes the longest time in the entire process, the collector thread can work together with the user thread, so, in general, the memory reclamation process of the CMS collector is executed concurrently with the user thread.
3 obvious flaws of the CMS collector:
- CMS collector is very sensitive to CPU resources
- The CMS collector cannot handle floating garbage and may fail with "Concurrent Mode Failure" leading to another Full GC
- CMS collector generates a lot of memory fragmentation
Floating garbage: Since the user thread is still running in the concurrent cleanup phase of the CMS, new garbage is naturally generated as the program runs. This part of garbage appears after the marking process, and the CMS cannot process it in the current collection, so it has to be in the next GC. Time to clean up.
G1 collector
G1 is a garbage collector for server-side applications. Has the following characteristics:
- Parallelism and Concurrency
- Generational collection
- Spatial integration: G1 is a collector based on the "mark-sort" algorithm as a whole, and based on the "copy" algorithm locally (between two regions), but in any case, both algorithms are implemented. It means that no memory space fragmentation will be generated during the operation of G1, and regular available memory can be provided after collection.
- Predictable pauses: In addition to the pursuit of low pauses, G1 can also establish a predictable pause time model, allowing users to explicitly specify that in a time segment of length M milliseconds, the time spent on garbage collection must not exceed N milliseconds
The operation of the G1 collector can be roughly divided into the following steps:
- initial mark
- concurrent marking
- Final Mark (requires Stop The World)
- Screening for recycling
5) Memory allocation and recovery strategy
Objects are first allocated in Eden
Objects are allocated in the new generation Eden area. When there is not enough space in the Eden area for allocation, the virtual machine will initiate a Minor GC.
The difference between Minor GC and Full GC:
- Cenozoic GC (Minor GC): The garbage collection action that occurs in the new generation. Because too many Java objects have the characteristics of rapid development, Minor GC is very frequent, and the recovery speed is generally faster.
- Old age GC (Major GC/Full GC): Refers to the GC that occurs in the old age, there is a Major GC, which is often accompanied by at least one Minor GC (but not absolute, in the collection strategy of the Parallel Scanvenge collector, there is a direct Perform the strategy selection process of the Major GC). Major GC is generally more than 10 times slower than Minor GC
Large objects go directly to the old age
The so-called large objects refer to Java objects that require a large amount of contiguous memory space. The most typical large objects are long strings and arrays.
Long-lived objects will enter the old age
An object age (Age) counter is defined for each object in the virtual machine. The age of an object increases by 1 year each time it passes through a Minor GC, and when its age increases to a certain level (15 years by default), it will enter the old age.
Dynamic object age determination
If the sum of the size of all objects of the same age in the Survivor space is greater than half of the Survivor space, objects whose age is greater than or equal to this age can directly enter the old age.
space allocation guarantee
Before Minor GC occurs, the virtual machine first checks whether the maximum available continuous space in the old generation is greater than the total space of all objects in the new generation. If the condition is true, it can ensure that the Minor GC is safe. If not, the virtual machine checks to see if the HandlePromotionFailure setting allows guarantee failures. If it is allowed, it will continue to check whether the maximum available continuous space in the old age is greater than the average size of the objects promoted to the old age. If it is larger, it will try to perform a Minor GC. If it is smaller, or the HandlePromotionFailure setting does not allow risk, then it is also To do a Full GC instead.
Chapter 4 Virtual Machine Performance Monitoring and Troubleshooting Tools
1) JDK command line tools
These tools are very small, because most of these command line tools are jdk/lib/tools.jar
a thin wrapper of the class library, and the main function code is implemented in the tools class library.
jps: virtual machine process status tool
Function: List the running virtual machine processes, and display the name of the virtual machine execution main class (the class where the main() function is located) and the local virtual machine unique ID of these processes
Main options:
jstat: Virtual Machine Statistics Monitoring Tool
Function: A command-line tool for monitoring various running status information of virtual machines.
Main options:
jinfo: Java configuration information tool
Function: View and adjust various parameters of the virtual machine in real time
jmap: Java Memory Mapping Tool
Function: Used to generate heap dump snapshots (heapdump or dump files). You can also query the finalize execution queue, Java heap and permanent generation details, such as space usage, which collector is currently in use, etc.
Main options:
jhat: virtual machine heap dump snapshot analysis tool
Function: Used in conjunction with jmap to analyze heap dump snapshots generated by jmap.
jstack: Java stack trace tool
Function: used to generate a thread snapshot of the current moment of the virtual machine (threaddump or javacore file)
A thread snapshot is a collection of method stacks that are being executed by each thread in the current virtual machine. The main purpose of generating a thread snapshot is to locate the cause of the thread's long pause, such as inter-thread deadlock, infinite loop, and long time caused by requesting external resources. Waiting, etc. are all common causes of thread stalls for long periods of time.
Main options:
2) JDK visualization tools
JConsole: Java Monitoring and Management Console
Visual monitoring and management tool based on JMX. The function of its management part is to manage JMX MBeans.
VisualVM: All-In-One Troubleshooting Tool
It is by far the most powerful runtime monitoring and fault handler released with the JDK. In addition to handling operation monitoring and troubleshooting, it also provides performance analysis.
In this article, we mainly made relevant reading notes for the second part of "In-depth Understanding of Java Virtual Machine: JVM Advanced Features and Best Practices". On the one hand, due to space reasons, we will release each part separately. On the other hand, it is to give readers enough time to digest. After all, one bite cannot make a big fat man~ Please read slowly and wait for the next part of the reading notes to be released! 👨💻
Don't talk empty-handed, don't be lazy, let's be a programmer who brags about the architecture with Xiaocai. Please pay attention to be a companion, so that Xiaocai is no longer alone. See you below!
👀 Work harder today, and you will be able to say one less word of begging tomorrow!
👉🏻 WeChat public account: Vegetable Farmer's Day, students who didn't pay attention, remember to pay attention!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。