The Huawei interviewer asked me: Do you really understand the Java garbage collector? I am angry! ! (︶︿︶)

The first stage : Serial garbage collector: Before jdk1.3.1, the Java virtual machine only supports the Serial collector
The second stage : Parallel Garbage Collector: With the emergence of multi-core, Java introduced a parallel garbage collector to make full use of multi-core performance to improve the efficiency of garbage collection
The third stage : Concurrent Markup Cleanup Collector CMS: Garbage Collector can run simultaneously with the application, reducing the time to suspend the execution of user threads
The fourth stage : G1 (concurrent) collector: The original intention is to meet the specific time of suspending the application when cleaning up a very large heap space, and there will be less memory fragmentation compared with CMS [Data acquisition]

1 Garbage collection algorithm

1-1 Mark removal algorithm

Algorithm overview

Advantages: fast recovery

Disadvantages: cause memory fragmentation, unable to allocate large contiguous space.

Algorithm idea

Before Java9, the default garbage collector used by Java was ParallelGC. Starting from Java9, G1 has been used as the default garbage collector

step1: For the first scan, use the GC root object to determine which objects in the heap memory can be garbage collected and mark them.

step2: For the second scan, to garbage collect the marked GC root objects, you only need to put the start memory address and the end memory address into the free memory area.

1-2 Marking Arrangement Algorithm

The first one is still a mark, and the second step will be a space arranging so as not to generate fragments.

Advantages : avoid memory fragmentation

Disadvantages : The organization of the space makes the efficiency relatively low.

1-3 Copy Algorithm [Data Acquisition]

Features:

Divide the managed memory into two areas, the from area and the to area, and copy the objects that do not need to be recycled from the from area to the to area. The memory area is organized during the copying process. Then exchange the points of from and to.

Advantages : no memory fragmentation

Disadvantages : double memory space is required, memory utilization is not high, and copying also takes time.



1-4 Summary of Three Garbage Collection Algorithms [Data Acquisition]

Garbage collection algorithmadvantageDisadvantage
Mark Sweep Algorithm (Mark Sweep)FasterGenerate memory fragmentation
Mark compaction algorithm (Mark Compact)No memory fragmentationSlow
Copy Algorithm (Copy)No memory fragmentationNeed to take up double the memory space

Note: The above three algorithms in the actual JVM garbage collection algorithm are used in combination.

2 JVM generational recovery algorithm

2-1 Overview

Garden of Eden: Garbage of Eden: Garbage

The Cenozoic is mainly composed of three parts, namely the Eden area, the surviving area from, and the surviving area to. Under normal circumstances, only the Eden area and the survivor area from will store the number, and the survivor area to is only used for garbage collection, and the copy object will be used. The young generation of heap memory undergoes a garbage collection (Minor GC), and most objects will be collected.
The old generation usually stores some frequently used objects. If an object survives many garbage collections, then the object will be put into the old generation from the young generation. Only when the new generation has insufficient memory and the old generation has insufficient memory, the full GC will be triggered to garbage collect objects in the old generation.

Why do we need to divide?

In the actual environment, the life cycle of the object is different. The object life cycle in the old age is relatively long, and it may take a long time for garbage collection. The object life cycle of the new generation is relatively short, and the garbage collection is more frequent. This partitioning method facilitates the use of different garbage collection algorithms for more effective garbage collection.

2-2 Generational garbage collection example

step1: The program has just started running, and the generated objects are put into the Eden area first, when the Eden area can't fit.

step2: Perform a Minor GC on the Eden area, and copy the survivor area To from objects that have not been garbage collected, and then exchange the survivor area To and the survivor area From. The final effect of the first garbage collection is shown in the following figure: step3: first Once a Minor GC, there is space in the Eden area that can be allocated to new objects. After a period of time, Eden is not enough. A second Minor GC is triggered. This time the garbage will check which objects from the Eden area and the surviving area can survive. And copy these objects to the surviving area To, and then swap the surviving area To and the surviving area From. At this time, the Eden area is vacant again, and new objects can be placed. In the actual garbage collection process, the JVM will record the number of times each object has survived garbage collection. For example, in the above figure, the number of garbage collections for two objects in the surviving area is 1 and 2, respectively. step4: When the number of times that some objects have been garbage collected and still survived reaches a threshold (indicating that the value of this object is relatively high), then this object will be moved to the old age. Extreme situation consideration: Eden area, from area, and elderly area are all full? At this time, Full GC will be triggered (Minor GC is prioritized, Minor GC is still not enough memory)







2-3 Summary of generational garbage collection

The object is first allocated in the Garden of Eden area

  • The new generation of space is insufficient, triggering minor gc, and Eden fromsurviving objects using copycopied to the to the survival of the
    target age plus 1 and exchangefrom to
  • minor gcWill trigger stop the world, suspend the threads of other users, wait until the garbage collection is over, the user threads will resume running. The
    pause time is short. Since most of the objects in the new generation are garbage and few objects are copied, the efficiency is higher.
  • When the life of the object exceeds the threshold, it will be promoted to the old age, the maximum life is 15 (4bit, object header storage)
  • When there is insufficient space in the old generation, it will try to trigger first minor gc, if there is still insufficient space afterwards, the trigger full gc,STWtime will be
    longer
  • Full GCThe stop the worldtime is longer than the MInor GCtime. There are more surviving objects in the old age and the space cleaning time, so the stop time will be longer.
    If the Full GCspace is still insufficient, an out of memory exception will be triggered.

Overview of the Garbage Collector

Parameter meaningparameterRemarks
Initial heap size-Xms
Maximum heap size-Xmx or -XX:MaxHeapSize=size
Cenozoic size-Xmn or (-XX:NewSize=size + -XX:MaxNewSize=size)NewSize is the initial size, and MaxNewSize is the maximum size.
Survival area ratio (dynamic)-XX:InitialSurvivorRatio=ratio and -XX:+UseAdaptiveSizePolicyThe ratio of the surviving area is 8 by default. Assuming that the Cenozoic memory is 10M, 8M is divided into the Eden area, and the remaining two halves, one from, one to.
Survival area ratio-XX:SurvivorRatio=ratioDynamically adjust the proportion of the survival area
Promotion threshold -XX:MaxTenuringThreshold=thresholdUsed to dynamically adjust the ratio of the survival area
Promotion details -XX:+PrintTenuringDistributionUsed to dynamically adjust the ratio of the survival area
GC details -XX:+PrintGCDetails -verbose:gcPrint detailed information
MinorGC before FullGC -XX:+ScavengeBeforeFullGCBy default, a Minor GC is performed before Full GC

2-5 Case Study of Garbage Collection

Case 1: Nothing is left
new generation: new generation tenured generation: old generation

package cn.itcast.jvm.t2;
import java.util.ArrayList;
/**
 *  演示内存的分配策略
 */
public class Demo2_1 {
    private static final int _512KB = 512 * 1024;
    private static final int _1MB = 1024 * 1024;
    private static final int _6MB = 6 * 1024 * 1024;
    private static final int _7MB = 7 * 1024 * 1024;
    private static final int _8MB = 8 * 1024 * 1024;
//加入Java开发交流君样:756584822一起吹水聊天
    // -Xms20M -Xmx20M -Xmn10M : 堆初始与最大大小都是20M,新生代的大小为10M.
    // -XX:+UseSerialGC : 为了学习方便,采用这个垃圾回收器,默认的垃圾回收器并不是这个。
    // -XX:+PrintGCDetails -verbose:gc :打印详细信息
    // -XX:-ScavengeBeforeFullGC :在Full GC 前进行 Minor GC.
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            ArrayList<byte[]> list = new ArrayList<>();
            list.add(new byte[_8MB]);
            list.add(new byte[_8MB]);
        }).start();

        System.out.println("sleep....");
        Thread.sleep(1000L);
    }
}

Case 1 execution result

It can be seen that even if the user does not create an object, the system object still occupies a part of the heap memory space.

Heap
 def new generation   total 9216K, used 2341K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
// 新生代的空间总的大小为9216K,这里没有把To空间给计算进去,系统任务To的空间是分配是不可用的,所以不是10M,已经使用了2341K,[]内部则是内存地址范围。                              
  eden space 8192K,  28% used [0x00000000fec00000, 0x00000000fee49420, 0x00000000ff400000)
//                                                          
  from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
                               
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
                               
 tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
// 老年代大小为10M,可以看到没有任何空间使用                                             
                                          //加入Java开发交流君样:756584822一起吹水聊天   
   the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
                                
 Metaspace       used 3394K, capacity 4496K, committed 4864K, reserved 1056768K
                                
  class space    used 378K, capacity 388K, committed 512K, reserved 1048576K

Are Java memory objects allocated on the heap?

Situation 2: The new generation heap space is full, triggering GC

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_7MB]);      // 系统类占用2341K,加上new的7MB触发垃圾回收
    }

Case 2 execution result

[GC (Allocation Failure) [DefNew: 2342K->696K(9216K), 0.0029193 secs] 2342K->696K(19456K), 0.0029867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
// GC:minor GC(新生代垃圾回收)    FUll GC  (老年代垃圾回收)
// [Times: user=0.00 sys=0.00, real=0.00 secs] 垃圾回收执行时间
Heap
 def new generation   total 9216K, used 8110K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  90% used [0x00000000fec00000, 0x00000000ff33d8c0, 0x00000000ff400000)
  from space 1024K,  67% used [0x00000000ff500000, 0x00000000ff5ae100, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
 //加入Java开发交流君样:756584822一起吹水聊天
  class space    used 395K, capacity 428K, committed 512K, reserved 1048576K

Situation 3: The new generation of memory can't fit as the number of objects increases

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_7MB]);
        list.add(new byte[_512KB]);
        list.add(new byte[_512KB]);
    }

Results of the

The new generation can't let go, and the objects of the new generation are placed in the old generation.

[GC (Allocation Failure) [DefNew: 2342K->670K(9216K), 0.0022591 secs] 2342K->670K(19456K), 0.0023131 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 8678K->538K(9216K), 0.0061246 secs] 8678K->8354K(19456K), 0.0061637 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 def new generation   total 9216K, used 1132K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,   7% used [0x00000000fec00000, 0x00000000fec94930, 0x00000000ff400000)
  from space 1024K,  52% used [0x00000000ff400000, 0x00000000ff486a00, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 7815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  76% used [0x00000000ff600000, 0x00000000ffda1f80, 0x00000000ffda2000, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
 //加入Java开发交流君样:756584822一起吹水聊天
  class space    used 395K, capacity 428K, committed 512K, reserveed 1048576K

Situation 4: At the beginning, the memory that is larger than the new generation is directly allocated, if the old generation is left, it is directly placed in the old generation

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_8MB]);
    }

Results of the

Heap
//加入Java开发交流君样:756584822一起吹水聊天
 def new generation   total 9216K, used 2507K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  30% used [0x00000000fec00000, 0x00000000fee72ca8, 0x00000000ff400000)
  from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  80% used [0x00000000ff600000, 0x00000000ffe00010, 0x00000000ffe00200, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
  class space    used 395K, capacity 428K, committed 512K, reserved 1048576K

to sum up

When the memory is tight, that is, when the new generation cannot be stored, sometimes the objects are directly allocated to the old generation, or the new generation objects are directly allocated to the new generation when the number of collections is small (less than 15 times). To the old age. 【Information Acquisition】

2 Garbage collector

2-1 Overview of Garbage Collector

nameFeaturesSuitable for the scenethe goalNew generationOld age
Serial garbage collectorSingle threadSmall heap memory, suitable for personal computers (number of CPUs)Replicated garbage collection algorithmUsing mark + sorting garbage collection algorithm
Throughput Priority Garbage CollectorMultithreadingLarge heap memory, multi-core CPUParallel, the shortest STW time per unit timeCopy algorithmMark + copy
Response time priority garbage collector (CMS for short)MultithreadingLarge heap memory, multi-core CPUConcurrency, make the single STW as short as possibleCopy algorithmThe memory fragmentation generated by the mark-sweeping algorithm needs to be degenerated into a single-threaded garbage collection collector

The CMS garbage collector was later replaced by the G1 garbage collector.

2-2 Serial Garbage Collector

JVM parameters to enable the serial garbage collector

-XX:+UseSerialGC    = Serial + SerialOld
// Serial:工作在新生代,采用复制的垃圾回收算法
// SerialOld:工作在老生代,采用标记+整理的垃圾回收算法


](https://jq.qq.com/?_wv=1027&k=0IsBuUb0)
Summary : When garbage collection is triggered, let multiple threads stop at a safe point, and then use a single-threaded garbage collector to perform garbage collection. After the garbage collection is complete, let other threads run.

2-3 Garbage collector with throughput priority

JVM parameters for enabling throughput-prioritized garbage collectors

Turn on/off parameters

The default multi-threaded garbage collector, the former is to turn on the new generation collector, using the copy algorithm, and the latter is to turn on the old generation collector, using the mark + copy algorithm. As long as one of the following options is enabled, the other one will also be enabled.

-XX:+UseParallelGC , -XX:+UseParallelOldGC 

Turn on adaptive and dynamic adjustment of the size of the new generation to increase the threshold

-XX:+UseAdaptiveSizePolicy 

Two index adjustment parameters (ParallelGC will adjust the heap size according to the set index to reach the target set below)
index 1) 1/(1+ratio) = garbage collection time/total running time

The default value of ratio is 99, which means that the garbage collection time does not exceed 1% of the total time. But it is generally set to 19. [Data acquisition]
If the target is not reached, ParallelGC will adjust the heap memory size to achieve this target, usually by increasing it, so that the number of garbage collections will be reduced, thereby increasing throughput

-XX:GCTimeRatio=ratio          

Indicator 2) The time limit for each garbage collection (the maximum number of milliseconds to pause)

The default value is 200ms.
Obviously reducing the heap memory space will help reduce the time of each garbage collection.

-XX:MaxGCPauseMillis=ms   

Summary: Obviously indicator 1) is in conflict with indicator 2).

-XX:ParallelGCThreads=n // Summary of the number of parallel garbage collection threads : Multi-threaded garbage collection is used. The number of garbage collection threads is usually set according to the number of CPU cores. In the garbage collection phase, parallel garbage collection threads will fully occupy the CPU. In the non-garbage collection phase, user threads will make full use of CPU resources.


2-4 Garbage collector with priority response time (CMS Garbage Collector)

Disadvantages: The memory fragmentation generated by the adopted mark-sweeping algorithm needs to be degraded into a single-threaded garbage collection collector, resulting in a longer response time.

Open JVM parameters

Note that this is a concurrent garbage collection that uses a mark-sweep algorithm. This is different from the previous garbage collector, which can run other non-garbage collection threads while garbage collection is performed (there are also time periods that need to be stopped, but not all Phase stopped).
The concurrent garbage collector of the old age will fail. At this time, the old garbage collector will degenerate into a single-threaded garbage collector (SerialOld)

-XX:+UseConcMarkSweepGC // use concurrent mark sweep(会产生垃圾碎片) 工作在老年代的垃圾回收器
-XX:+UseParNewGC        // 工作在新生代的垃圾回收器
//加入Java开发交流君样:756584822一起吹水聊天

Important initial parameters

-XX:ParallelGCThreads=n        // 并行的垃圾回收线程数,通常等于CPU的核心数(垃圾回收并行阶段)
-XX:ConcGCThreads=threads      // 并发的线程数目,通常设为并行垃圾回收线程数的1/4(垃圾回收并发阶段)

Other parameters

-XX:CMSInitiatingOccupancyFraction=percent // 执行垃圾回收的内存占比,预留空间给浮动垃圾
-XX:+CMSScavengeBeforeRemark
// 在重新标记前,对新生代进行垃圾回收,减少并发清理的垃圾对象,+开启,-关闭



Floating garbage refers to the garbage newly generated by the user thread in the concurrent cleaning process, and it needs to wait for the next concurrent cleaning. 【Information Acquisition】

Concurrent workflow overview:

  • step1: The memory is not stored in the old age.
  • step2: ConcMarkSweepGC will perform an initial marking action (initial marking requires STW to block non-garbage collection threads). The initial marking only marks the root object, so the speed is very fast and the pause time is very short.
  • step3: After the initial marking is completed, the previously blocked thread can run again. At this time, the garbage collection thread performs concurrent marking.
  • step4: After the concurrent marking is over, the non-garbage collection thread needs to be blocked again to perform a so-called remarking.
  • step5: After the remarking is complete, the blocked thread can run again. Garbage collection threads also clean up garbage objects concurrently.

Summary : Initial marking and remarking need to block threads. In the concurrent phase, because garbage collection threads occupy resources, the throughput of the system will be affected to a certain extent, but the response speed of the system will not be significantly affected by garbage collection due to concurrent execution (compared to other garbage collectors, STW time only needs Perform initial marking and re-marking, and can mark and remove garbage without blocking other threads).

Finally, I wish you all early success in your studies, get a satisfactory offer, get a quick promotion and raise your salary, and reach the pinnacle of life.

【references】

Insert picture description here