Preface:

Today, I’m going to share some information about the JVM. I’m going to focus on the CMS and G1 collectors. In my experience, these are the two collectors that get asked the most questions, and I’m going to give priority to these two, but, I say but, if you follow me there’s a lot more you can learn about the JVM, so I’m sure you’ll get a lot more out of it.

The relationship between collector and JVM heapCopy the code

CMS collector

JVM parameters: -xx :+UseConcMarkSweepGC

The CMS (Concurrent Mark Sweep) collector was the HotSpot VIRTUAL machine’s first truly Concurrent collector, enabling the garbage collector thread to work (basically) at the same time as the user thread. -xx :+UseConcMarkSweepGC to start the CMS

As the word Mark Sweep in its name implies, the CMS collector is implemented as a mark-and-sweep algorithm, which is a bit more complex than the previous garbage collectors. The whole process is divided into four steps:

Initial flag: Suspend all other threads and log objects directly connected to GC root, which is fast;

Concurrent marking: Enable both GC and user threads, using a closure structure to record reachable objects. At the end of this phase, however, the closure structure is not guaranteed to contain all currently reachable objects. Because the user thread may be constantly updating the reference field, the GC thread cannot guarantee real-time accessibility analysis. So the algorithm keeps track of where these reference updates happen.

Relabelling: The relabelling phase is to correct the mark record of the part of the object that the mark changes because the user program continues to run during the concurrent marking phase. The pause time of this phase is usually slightly longer than the initial marking phase, and much shorter than the concurrent marking phase

Concurrent cleanup: The user thread is started and the GC thread begins to clean the marked area.

CMS collector tests:

CMS parameter configuration:

-Xmx200M -Xmn50m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseConcMarkSweepGC
Copy the code

Output the following GC logs:

CMS process:

2020-01-05T21:52:05.411+0800: [GC (CMS Initial Mark) [1 CMS-initial-mark: [Times: 72364K(77824K)] 77550K(123904K), 0.0010600secs] [Times: User =0.00 sys=0.00, real=0.00 secs] 220-01-05T21:52:05.412 +0800 [CMS-concurrent-mark-start] 2020-01-05T21:52:05.416+0800: [CMS-concurrent-mark: 0.004/0.004 secs] [Times: User =0.00 sys=0.00, real=0.00 secs] Step 3: [cmS-concurrent-preclean-start] 2020-01-05T21:52:05.417+0800: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: The user sys = = 0.00 0.00, [cms-concurrent-abortable-preclean-start] [CMs-concurrent-abortable-preclean: [Times: user=0.00 sys=0.00, real=0.00 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (CMS Final Remark) [YG occupancy: 5185K (46080k)]2020-01-05T21:52:05.417+0800: [Rescan (Parallel), 0.0003800 SECs]2020-01-05T21:52:05.417+0800: [Weak Refs Processing, 0.0006763 secs]2020-01-05T21:52:05.418+0800: [class unloading, 0.0009691 secs] 2020-01-05 T21:52:05. 419 + 0800: 2020-01-05T21:52:05.421+0800: [Scrub Symbol table, 0.0019453 secs]2020-01-05T21:52:05.421+0800: [Scrub String table, 0.0004832 secs] [Times: 72364K(77824K)] 77550K(123904K), 0.004650secs] [Times: 2020-01-05T21:52:07.174+0800: user=0.02 sys=0.00, real=0.00 [CMS-concurrent-sweep-start] 2020-01-05T21:52:07.175+0800: [CMS-concurrent-sweep: 0.0000/0.0000secs] [Times: User =0.00 sys=0.00, real=0.00 secs] Step 7 Reset 2020-01-05T21:52:07.175+0800: [cms-concurrent-reset-start]Copy the code

2020-01-05T21:52:07.176+0800: [cmS-concurrent-reset: 0.0000/0.0000secs][Times: user=0.00 sys=0.00, real=0.00 secs]

There are seven steps to summarize the CMS collector process:

  1. Initial mark (CMS-initial-mark), which results in SWT;
  2. Concurrent mark (cmS-concurrent-mark), which runs concurrently with the user thread;
  3. Preclean (cmS-concurrent-preclean), running at the same time as the user thread;
  4. Abortable preclean (cmS-concurrent-abortable-preclean) runs at the same time as the user thread;
  5. Re-marking (CMS-remark) will result in SWT;
  6. Concurrent sweep (cmS-concurrent-sweep), which runs concurrently with the user thread;
  7. Concurrent state reset waits for the next CMS trigger (cms-concurrent-reset), running concurrently with the user thread;

Advantages and disadvantages of CMS collector:

Main advantages: Concurrent collection, low pauses.

But it has the following three obvious disadvantages:

· Sensitive to CPU resources;

· Unable to handle floating garbage;

Algorithm, it USES – “tag – clear” * * * * algorithm can lead to when it has a lot of space debris gather over (don’t do sorting – XX: CMSFullGCsBeforeCompaction = n after how many times do compression).

G1 collector

JVM parameters: -xx :+UseG1GC** **

G1 (garbage-First) is a server-based Garbage collector, mainly for machines equipped with multiple processors and large memory capacity. High throughput performance characteristics while meeting the GC pause time requirements with extremely high probability.

Is seen as an important evolutionary feature of the HotSpot virtual machine in JDK1.7. It has the following characteristics:

Parallelism and concurrency: The G1 takes full advantage of CPU, multi-core hardware, and uses multiple cpus (cpus or CPU cores) to reduce stop-the-world pause times. While other collectors would have paused GC actions performed by Java threads, the G1 collector can still allow Java programs to continue executing concurrently.

G1 divides the Java heap into independent regions of equal size, and the JVM can have up to 2048 regions **. 天安门事件

The size of a Region is equal to the size of the heap divided by 2048. For example, if the heap size is 4096 MB, the Region size is 2 MB. Of course, you can manually specify the Region size with the parameter “-xx :G1HeapRegionSize”, but the default calculation method is recommended.

G1 retains the concept of young and old, but instead of being physically separated, they are collections of (potentially discontinuous) regions.

If the heap size is 4096 MB, the young generation occupies about 200MB of memory, which corresponds to about 100 regions. You can run the -xx :G1NewSizePercent command to set the initial proportion of the new generation. During system operation, The JVM keeps adding more regions to the younger generation, but at most the new generation does not account for more than 60%, which can be adjusted by “-xx :G1MaxNewSizePercent”. The region corresponding to Eden and Survivor in the young generation is the same as before, the default is 8:1:1. Assume that the young generation now has 1000 regions, including 800 Eden regions, 100 S0 regions and 100 S1 regions.

A Region may be a young generation. If a Region performs garbage collection, it may become an old generation. In other words, the Region functions of a Region may change dynamically.

The G1 garbage collector applies the same principles to when objects are migrated to older regions, except for the fact that G1 has a Region called Humongous that allocates large objects, rather than allowing large objects to move directly into older regions. In G1, the rule for determining large objects is that a large object exceeds 50% of the size of a Region. For example, according to the above calculation, each Region is 2M. If a large object exceeds 1M, it will be placed into Humongous.

Humongous area is dedicated to storing short-term giant objects. It is not necessary to directly enter the old age, which can save the space of the old age and avoid GC overhead due to insufficient space of the old age.

In Full GC, Humongous will be collected as well as young and old generations.

G1 Parameter Configuration:

-Xmx200M -Xmn50m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseG1GC
Copy the code

G1 collector Tests:

The following logs are displayed:

The 2020-01-08 T13: so. 126 + 0800: [GC Pause (G1 Humongous Allocation) Initial-mark (Young), 0.0023830 secs] [Parallel Time: 1.1ms, GC Workers: 8] [GC Worker Start (MS): Min: 162.8, Avg: 162.8, Max: 162.9, Diff: 0.0]
      [Ext Root Scanning (ms): Min: 0.3, Avg: 0.5, Max: 0.9, Diff: 0.6, Sum: 3.8in: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0in: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.0, Avg: 0.4, Max: 0.5, Diff: 0.5, Sum: 2.8]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.2]
         [Termination Attempts: Min: 1, Avg: 7.3, Max: 11, Diff: 10, Sum: 58in: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.3]
      [GC Worker Total (ms): MinGC Worker End (ms): Min[Code Root Fixup: 0.0 ms] [Code Root Purge: 0.0 ms] [Clear CT: [Ref Proc: 0.1ms] [Ref Enq: 0.1ms] [Redirty Cards: 0.5ms] [Humongous Reclaim: 0.0ms] [Free CSet: 0.0ms] 3072.0K(50.0m)-> 0.0b (49.0m) Survivors: 0.0b ->1024.0K Heap: 30.5m (126.0m)-> 28.8m (126.0m)] [Times: Survivors: 0.0b ->1024.0K Heap: 30.5m (126.0m)-> 28.8m (126.0m)] Sys =0.00, real=0.00 secs] 2020-01-08T13:19:36.129+0800: [GC concurrent - root - region - scan - start] 2020-01-08 T13: so. 135 + 0800: [GC concurrent-root-region-scan-end, 0.0060575 secs] 2020-01-08T13:19:36.135+0800: [GC concurrent - mark - start] 2020-01-08 T13: so. 135 + 0800: [GC concurrent-mark-end, 0.0000731 secs] 2020-01-08T13:19:36.135+0800 [GC 2020-01-08T13:19:36.135+0800] [Finalize Marking, 0.0002335 SECS] 2020-01-08T13:19:36.136+0800: 2. [GC ref-proc, 1 class = 1 class = 1 class = 1 class] [Times: 1 class = 1 class] User =0.00 sys=0.00, real=0.00 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]Copy the code

The G1 collector process has four steps:

Initial mark (STW) : Pauses all other threads and records objects that GC Roots can reference directly, very fast;

Concurrent Marking: Final Marking (STW) : re-marking with CMS

* Filter Cleanup (STW) : In the filter collection phase, the collection value and cost of each Region are sorted, and the collection plan is made according to the expected GC pause time (which can be specified by JVM parameter -xx :MaxGCPauseMillis). For example, in the old days, 1000 regions are full. However, according to the expected pause time, this garbage collection may only pause for 200 milliseconds, so according to the previous calculation of the cost of collection, it may take 200ms to reclaim 800 regions, so only 800 regions will be reclaimed, and try to control the pause time caused by GC within the specified range. This phase can be executed concurrently with the user program, but since only part of the Region is reclaimed, the time is controlled by the user, and suspending the user thread greatly improves collection efficiency. Whether in the young generation or the old generation, the reclamation algorithm mainly uses the replication algorithm, which copies the surviving objects in one region to another region. This method will not complete the reclamation like CMS because there are many memory fragments that need to be sorted. G1 uses the replication algorithm to recycle almost no memory fragments.

Advantages and disadvantages of G1 collector:

The G1 takes full advantage of The hardware advantages of cpus and multi-core environments, using multiple cpus (cpus or CPU cores) to shorten stop-the-world pause times

Cons: G1 as a whole is a collector based on the “mark-up” algorithm; From the local point of view is based on ** “copy” algorithm to achieve **, there is a certain “waste” of memory usage.

Conclusion:

Can see this are awesome people, trouble to help click a like attention, next I continue to bring CMS and G1 combat PK comparison, graphical comparison to see more intuitive.

Pay attention and don't get lost.Copy the code