1. Memory generation model
Why talk about the JVM’s memory generation model, because memory generation is related to the running of the garbage collector.
Most of the garbage collectors in use today are logically generational, with the exception of G1 being both logically and physically generational.
- GC except Epsilon, ZGC and Shenandoah are all logical generation models
- G1 is a logical generation, not a physical generation
- In addition, there is not only logical but also physical generation
Logical generation is “to make some conceptual distinctions between memory”, physical generation is true physical memory.
“The specific division“
The young and the old.
“New generation” : those objects that have just come out
“Old age” : An old object that has been recycled many times without being recycled
The New generation is divided into:
- The default Eden ratio is 8. The new object is placed in the Eden area.
- The default ratio of survivor (S1) is 1. Garbage collection once goes to this area, which stores different objects and adopts different garbage collection algorithms.
- The default ratio of survivor (S2) is 1.
One generation of surviving objects is using Copying algorithms.
In the old days, when there were many living objects, the garbage collection algorithm applied Mark Compact or Mark Sweep.
“Several GC concepts“
- MinorGC/YGC Garbage collection triggered when the MinorGC generation runs out of space.
- MajorGC/FullGC is triggered when the old generation can no longer allocate space, and the new generation and the old generation collect garbage at the same time.
“Configure generation space parameters“
-Xms-Xmx
-Xmn
Copy the code
X is a non-standard parameter, m is memory, s is the minimum, X is the maximum, and n is new
2. The life course of an object – from birth to death
After an object is new, it will first try to allocate it on the stack. If there is no more allocation on the stack, it will enter Eden area.
Eden entered a survivor zone – S1 after a garbage collection.
After a garbage collection, survivor zone (S1) enters another survivor zone, S2, and some objects in Eden zone also enter S2.
When an object ages to a certain value, it enters the old section. This value can be obtained with arguments:
-XX:MaxTenuringThreshold
Copy the code
Configure.
The following diagram helps us understand the concept of memory partitioning in the JVM.
3. How are objects allocated on the stack
Struct structures in C can be allocated directly on the stack, and there is also the idea of allocation on the stack in Java.
In the JVM, “the heap is thread shared,” so objects on the heap are shared and visible to individual threads, and “object data stored in the heap can be accessed as long as a reference to the object is held.” A virtual machine’s garbage collection system can “reclaim objects that are no longer used in the heap,” but for the garbage collector, either filtering the recyclable objects or reclaiming and defragmenting memory is “time consuming.”
“An object can be allocated on the stack if it is certain that its scope will not escape the method,” so that the memory occupied by the object can be “destroyed as the stack frame goes off the stack.” In a typical application, the proportion of local objects that do not escape is large, and if stack allocation is used, a large number of objects are automatically destroyed at the end of the method, without needing to be collected by the garbage collector, thereby “reducing the garbage collector’s load.”
The JVM allows “thread-private objects to be broken up and allocated on the stack” rather than on the heap. The advantage of allocation on the stack is that “it can be destroyed at the end of the function call without the intervention of the garbage collector, thus improving system performance.”
To sum up, “Allocation on the stack:”
- “Thread private small object“
- “There is no escape“
Used in a piece of code that no other code knows about.
For example, if an object has two fields, they are allocated as local variables.
- “Support for scalar substitution“
Replacing an object with a common property, a common type, is called a scalar substitution.
This means that the JVM allows objects to be split and allocated on the stack, such that if an object has two fields, they are allocated as local variables.
- “Don’t need to adjust“
Objects allocated on the station are destroyed as the stack frame goes off the stack without memory adjustment.
4. Thread local allocation
Objects are no longer allocated on the stack, so local allocation is preferred.
Thread Local Allocation Buffer, TLAB for short.
Many threads allocate objects to Eden area. The thread allocating objects will requisition the memory space, and the one who grabs it will be the one who takes it. When multithreaded synchronization occurs, efficiency is reduced, so this TLAB mechanism, thread-local allocation, is designed.
TLAB features:
- The size mode of occupying Eden area is 1%. This 1% space is unique to threads, and objects are allocated to this space first.
- When multi-threading, you can apply for space without competing for Eden area, which improves efficiency.
- You allocate small objects.
- No adjustment required.
Let’s test whether allocation on the stack and TLAB improves efficiency.
public class TLABTest {
// -xx: -doescapeAnalysis Removes escape analysis
// -xx: -eliminateallocations removes scalar substitutions
// -xx: -usetlab
public static void main(String[] args) { TLABTest t = new TLABTest(); long start = System.currentTimeMillis(); // Execute alloc 10 million times for (int i = 0; i < 1000 _0000; i++) { t.alloc(i); } long end = System.currentTimeMillis(); System.out.println("spends " + (end - start)); } // This method just creates an object without any reference to it. // No one knows it except this method, so there is no escape void alloc(int id) { new User(id, "name" + id); } class User { int id; String name; public User(int id, String name) { this.id = id; this.name = name; } } } Copy the code
Add to execution
-XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB
Copy the code
- -xx: -doescapeAnalysis Deletes escape analysis
- -xx: -eliminateAllocations removes scalar substitutions
- XX: – UseTLAB remove TLAB
Running results:
spends 1237
Copy the code
Then cross -xx: -doescapeanalysis-xx: -eliminateAllocations -xx: -usetLab, which is the default:
spends 643
Copy the code
Efficiency is obviously improved!
5. Common garbage collectors
5.1 “Serial”
When Serial is running, all running threads stop.
Thread stops have a “safe point” at which a thread needs to be stopped. This garbage collector has a longer pause time (” stw-stop The World “) and is now used less frequently.
5.2 Serial Old
Used in the old days, also “STW,” using mark-sweep, single-threaded.
5.3 Parallel Insane
The default is to be “Parallel Insane” and “Parallel Old” (PS+PO) if the JVM has not done any parameter setting.
The Parallel Scavenge is different from the Serial Insane.
5.4 “Parallel Old”
For the old STW, multi-threaded execution, using mark-compact.
5.5 “ParNew”
The Parallel Avenge. It’s just a little bit of an enhancement to PS and it works with CMS, which runs with ParNew at a certain stage.
The rest of the threads cannot work while ParNew is working and must wait for the GC to finish.
It also works STW, using the Copying algorithm and executing in multiple threads.
5.6 “CMS”
The first few garbage collectors have a common character is STW, that is, when my garbage collector is working, no one else can move, you have to wait, I finished, you can continue to work.
CMS was born to try to solve this problem. However, CMS itself has many problems, and the default garbage collector for any current JDK version is not a CMS.
Cms-concurrent Mark Sweep, Concurrent Mark Sweep. From a thread perspective, the CMS does garbage collection at the same time as the worker thread, but it’s still slow.
In the past, when the memory is small, the speed is very fast, but now the server memory has been very large, equivalent to the original 10 square meters in the room to clean up the garbage, now need to clean up the garbage in 100 square meters or even larger space, even if the use of multithreading to clean up also takes a long time.
“The four phases of a CMS“
- “CMS Initial Mark Indicates the initial marking phase“
This phase “STW”, “directly finds the object at the root and marks it”, other objects are not marked.
- “CMS Concurrent Mark Concurrent marking phase“
GC “wastes 80% of its time in the concurrent marking phase”. So this phase runs at the same time as the worker thread, and the client may feel slower, but at least it’s still responsive.
The worker thread marks the garbage as it generates it. This process cannot be completed, so the re-mark phase occurs.
- “CMS Remark Re-marking phase“
This is also an “STW”, new garbage generated during the concurrent marking phase, which is re-marked and requires the worker thread to stop, which is not very long.
- “CMS Concurrent sweep Concurrent sweep phase“
In this phase, a worker thread is also running, so new garbage will be generated during the execution. This garbage is called “floating garbage”. “Floating garbage will be cleaned up when the CMS runs next time”.
“Triggering conditions of the CMS“
In the old days, the CMS is triggered when the allocation is exhausted, and the initial flag is single thread, and the re-flag is multi-thread.
“The disadvantage of the CMS“
- Memory Fragmentation Memory Fragmentation
If the memory is very large, objects from the young generation to the old generation will not find space if the old generation generates a lot of memory fragmentation -PromotionFailed.
CMS introduced Serial Old, an ancient collector that uses a single thread for mark compression, and you can imagine the efficiency.
-XX:+UseCMSCompactAtFullCollection
- XX: refers to how many times before FGC CMSFullGCsBeforeCompaction default to 0 is compressedCopy the code
- Floating Garbage
You can set parameters to lower the threshold for triggering the CMS.
- XX: CMSInitiatingOccupancyFraction 92% can reduce the value, let the old s has enough spaceCopy the code
5.7 “G1”
G1 can also perform concurrent garbage collection. Compared with CMS, G1 has the following advantages:
- G1 defragment memory during GC without creating a lot of memory fragmentation
- G1’s STW is more controllable, allowing you to specify the expected GC pause times
In G1, memory regions are divided into discontinuous regions. Each Region is contiguous internally.
Humongous (H) indicates that these regions store Humongous objects (H-OBJ) – “objects that are more than half the size of a Region”.
The size of a Region can be determined by parameters
-XX:G1HeapRegionSize
Copy the code
Set. The value ranges from 1M to 32M and is an exponent of 2. If not, G1 will automatically determine the Heap size.
5.8 “ZGC”
ZGC is a “concurrent”, “non-generational”, “region-based, NUMA-enabled compression collector”. Because STW is only used during the enumeration of root nodes, “the pause time does not increase with heap size or the number of live objects.”
“The goal of ZGC“
- The garbage collection pause time does not exceed 10ms
- Both relatively small heaps (hundreds of MEgabytes) and large ones (terabytes) can be handled with ease
- Throughput drops by no more than 15% compared to G1
- This can be used to implement new GC features and further optimize the collector using Colored Pointers and read barriers
6. Reference materials
- Getting Started with the G1 Garbage Collector
- Java Garbage Collection Basics
- Wiki.openjdk.java.net/display/zgc…
The first public account “Xingbaili ER”, welcome old iron attention reading correction. Also visit me at “GitHub” github.com/xblzer/Java…