This article is too hardcore and is recommended for those with Java experience.

Introductions to the 0.

When it comes to THE JVM, GC is probably the first thing that comes to mind for most people. Today we are going to talk about the garbage collector and the garbage collection algorithm, hoping that through this article, you can have a general understanding of GC.

1. Run time data area

During execution, the JVM divides the memory it manages into several different data regions. These zones have their own purposes and creation and destruction timings, with some zones persisting with the start and end of a virtual machine process and others being created and destroyed depending on the start and end of user threads. According to the Java Virtual Machine Specification, the memory managed by the Java Virtual Machine will include the following runtime data areas:

1.1 Program counter

The line number that points to the bytecode being executed by the current thread is essentially a piece of memory that keeps track of where the current program is running. The job of the bytecode interpreter is to change the value of this counter to select the next bytecode instruction that needs to be executed. Branches, loops, jumps, exception handling, thread recovery, and so on all depend on this counter.

Since Java multithreading is done by switching threads in turn, a thread needs something to keep track of where it is when it has not finished executing, starting from there the next time it grabs CPU resources. This thing is the program counter, and because of this, it is also “thread-private” memory.

If a thread executes a primary method, this counter records the address of the virtual machine bytecode instruction being executed. If a local method is being executed, the value of this counter is empty, and this memory region is the only one where Java’s virtual machine specification does not specify any OutOfMemoryError exceptions.

1.2 Java Virtual Machine Stack

Like program counters, the Java Virtual Machine Stack is off-the-shelf and private, with the same life cycle as a thread.

The virtual machine Stack describes the threaded memory model of Java method execution: For each method execution, the Java VIRTUAL machine synchronously creates a Stack Frame to store information about local variables, operand stacks, dynamic connections, method exits, and so on. The process of each method being called and executed corresponds to the process of a stack frame moving from the virtual machine stack to the virtual machine stack.

There are often people who divide The Java memory region into Heap and Stack. This division directly inherits from the traditional C and C++ program memory layout structure, which is somewhat rough in the Java language. The actual memory region division is more complex than this. But it also shows that programmers are really focused on the “heap” and the “stack,” and the “stack” usually refers to the Java virtual machine stack, or more often just the local variable table portion of the virtual machine stack.

1.3 Local method stack

The role of Native Method Stacks is very similar to that of the virtual machine stack, except that the virtual machine stack performs Java methods (i.e. bytecodes) for the virtual machine, whereas the Native Method stack services the Native methods used by the virtual machine.

1.4 Java heap

The Java Heap is the largest chunk of memory managed by a virtual machine. The Java heap is an area of memory that is shared by all threads and is created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and “almost” all object instances in the Java world are allocated memory here.

1.5 method area

The Method Area, like the Java heap, is an Area of memory shared by threads that stores data such as type information that has been loaded by the virtual machine, constants, static variables, and code caches compiled by the just-in-time compiler. Although the Java Virtual Machine Specification describes the method area as a logical part of the Heap, it has an alias called “non-heap” to distinguish it from the Java Heap.

Permanent Generation is the term that most programmers use to develop and deploy applications on Hotspot virtual machines. In fact, the term is not equivalent to Permanent Generation. It’s just that the Hotspot team implemented the method area using a “persistent generation”, which allows Hotspot to manage the memory in the same way that it manages Java heap memory. In fact, in retrospect, it wasn’t a good idea to implement the method area using a “persistent generation”. This design makes Java more prone to memory overflow problems. Because the permanent generation has an upper limit of -xx: MaxPermSize, it has a default size even if it is not set. Even in some large projects, the startup fails without setting this parameter. I have worked with more than one such project.

There is no permanent generation concept. In JRockit and J9, there is no problem as long as there is no upper limit of memory available to touch processes, which is 4GB on 32-bit systems.

Garbage collector

2.1 Serial Collector

The Serial collector is the most basic and oldest collector and was once (prior to JDK 1.3.1) the only choice for the new generation of HotSpot VIRTUAL machine collectors.

Serial is a single-threaded collector, which is not limited to garbage collection, but more importantly requires all threads to be stopped until it is finished.

2.2 PerNew collector

The PerNew collector is essentially a multithreaded parallel version of Serial.

PerNew isn’t much different from Serial except that it supports multi-threaded parallel collection, but it is the preferred next-generation collector for HotSpot virtual machines running in server-side mode, especially in legacy systems prior to JDK 7.

There is an important reason for this, which has nothing to do with functionality or performance, because PerNew is currently the only one other than Serial that works with CMS.

2.3 Parallel Scavenge

The Parallel Collector is a new generation collector. It is also based on the mark-copy algorithm and is a multi-threaded collector that can collect in Parallel.

It looks like PerNew, but the Parallel Insane is focused on achieving a controlled Throughput.

Throughput = time to run user code/(time to run user code + time to run garbage collection)Copy the code

The Parallel Scavenge collector provides two parameters for precise throughput control, the -xx: MaxGCPauseMillis parameter, which controls the maximum garbage collection pause time, and the -xx: GCTimeRatio parameter, which directly sets the throughput size.

  • -xx: MaxGCPauseMillis: The allowed value of the parameter is a value greater than 0 milliseconds. The collector will try to ensure that the memory reclamation time does not exceed the user set value.
  • -xx: GCTimeRatio: The value of this parameter should be an integer ranging from 0 to 100. It is the ratio of garbage collection time to total time, which is the inverse of throughput.

2.4 Serial Old Collector

Serial Old is an older version of the Serial collector, which is also a single-threaded collector using a mark-collation algorithm.

2.5 Parallel Old collector

Parallel Old is an older version of the Parallel Avenge collector, supported by multiple threads for concurrent collection and implemented on a mark-collation algorithm. This collector was not available until JDK 6.

2.6 CMS Collector

The CMS (Concurrent Mark Sweep) collector is a collector whose goal is to obtain the shortest collection pause time.

Its operation process is more complex than the previous several collectors, the whole process is divided into four steps, including:

  1. CMS Initial Mark
  2. CMS Concurrent Mark
  3. Re-marking (CMS Remark)
  4. CMS Concurrent sweep

In this process, the “initial mark” and “re-mark” processes still need to stop all current processes and execute them separately.

The initial tag simply marks objects that GC Root can associate with, which is fast.

Concurrent marking is the process of traversing the entire object graph starting with the directly associated objects of GC Roots. This process is time-consuming but does not require stopping the user thread, and can be run in parallel with the user thread.

Re-marking is to correct the marking record of the part of the object that is marked during concurrent marking because the user program continues to operate. The pause time in this phase is longer than the initial marking time, but also much shorter than the concurrent marking time.

Concurrent cleanup, in which the cleanup removes objects that have been marked as dead, can also be done concurrently with the user thread, since there is no need to move live objects.

2.7 Garbage First collector

Garbage First is what became known as the G1 collector, a landmark in the history of Garbage collector technology that pioneered the idea of local collection-oriented design and region-based memory layout.

  • Initial tag: Just mark the objects that GC Roots can associate directly with, and change the value of the TAMS pointer so that the next phase of user threads running concurrently will allocate new objects correctly in the available regions. This phase requires the thread to pause, but it is very short, and it is done synchronously during the Minor GC, so the G1 collector actually has no additional pauses during this phase.
  • Concurrent marking: Reachability analysis of objects in the heap is performed starting with GC Root, recursively scanning the entire heap object graph for objects to reclaim. This phase is time-consuming, but can be performed concurrently with user programs. When the object graph scan is complete, it is also necessary to reprocess the objects recorded by SATB that have reference changes at the time of concurrency.
  • Final mark: Another short pause is made on the user thread to deal with the last few SATB records that remain after the end of the concurrent phase.
  • Filter recycling: Update statistics of regions, sort the collection value and cost of each Region, and make a collection plan based on the pause time expected by users. You can select multiple regions to form a collection. The surviving objects of the Region are then copied to the empty Region, and the entire space of the old Region is cleared. The operation here involves the movement of the living object, which must suspend the user thread, and is done in parallel by multiple collector threads.

Can be seen from the above the description of the stage, the G1 collector besides concurrent tags, the rest of the stages are to be fully suspended user thread, in other words, it is not a purely pursue low latency, official target is to it as much as possible in the case of delay controllable gain high throughput, so can bear the burden of “full-function collector” and hopes.

Garbage collection algorithms

Garbage collection is based on generational collection. In general, we classify garbage collection as follows:

  1. Partial GC: Garbage collection that does not aim to collect the entire Java heap.
    1. Minor /Young GC: Garbage collection that targets only the new generation.
    2. Major GC: Garbage collection that targets only Old GC.
  2. Mixed GC: Garbage collection that aims to collect the entire new generation and parts of the old generation. Currently, only the G1 collector has this behavior.
  3. Full GC: Collects the entire Java heap and method area garbage collection.

3.1 Mark-clear algorithm

Mark-sweep algorithm is the earliest and most basic garbage collection algorithm. Most of the subsequent algorithms are based on the mark-sweep algorithm to improve its shortcomings.

The specific execution process of the mark-clear algorithm is as follows:

This algorithm has two big flaws:

  • Execution efficiency is unstable: If the Java heap contains a large number of objects, most of which need to be recycled, then a large number of marking and cleaning actions must be performed, resulting in the efficiency of both marking and cleaning processes decreasing as the number of objects increases.
  • Memory space fragmentation: A large number of discrete memory fragments are generated after marking and clearing. Too much space fragmentation may result in the failure to find sufficient contiguous memory when large objects need to be allocated during a later program run and another garbage collection action has to be triggered in advance.

3.2 Mark-copy algorithm

Tag – copy algorithm is a half area of garbage collection algorithm, it will memory size according to the capacity is divided into two pieces of equal size, using only one piece, every time when this block is used up, again will still alive object replication to another piece of the above, then have used all the clear, specific implementation process is as follows:

The obvious drawback is that the available memory is cut in half.

IBM puts it more quantitatively: 98% of the new generation of objects will not survive the first round of collection, so there is no need to divide the memory space of the new generation by 1:1.

Andrew Appel proposed a more optimized half-region replication generation strategy for the objects with the characteristics of “procreation and extinction”, which is now called “Appel collection”.

The Serial and ParNew collectors of the HotSpot VIRTUAL machine all adopt this strategy to design the memory layout of the new generation.

Specifically, the new generation is divided into one large Eden space and two small Survivor Spaces. Each time memory is allocated to Eden space and one Survivor space, when garbage collection occurs, The surviving objects in Eden and Survivor are copied to another Survivor space once, and then Eden and the used Survivor space are cleaned up directly.

Since no one can say for sure that the surviving objects of each garbage collection will be placed into the Survivor space, the garbage collection algorithm also designs an “escape door” to ensure that if the Survivor space cannot accommodate the objects after one garbage collection, You need to rely on other regions (mostly older ones) for distribution guarantees (Handle Promotion).

3.3 Mark-collation algorithm

Since most objects in the old age are not recycled, the mark-copy algorithm is not suitable for the old age garbage collection algorithm, so a new algorithm is needed to deal with the old age garbage collection.

– sorting algorithm arises at the historic moment, marking – sorting algorithm and tag – clear algorithm is very like, mark – sorting algorithm of subsequent steps are not directly with their recyclable garbage sorting, but let all live objects to space at one end of the move, and then get rid of the rest of the memory, the concrete implementation process is as follows:

reference

Understanding the Java Virtual Machine: Advanced JVM Features and Best Practices by Zhiming Zhou

Blog.csdn.net/fanxing1964…


This article is constantly updated, you can search “Geek excavator” on wechat to read it in the first time, and the key words in reply have all kinds of tutorials PREPARED by me, welcome to read.