This tutorial is to understand basic Java garbage collection and how it works. This is the second part of the garbage collection tutorial series. I hope you have read the first part: " A brief introduction to Java garbage collection mechanism ".
Java garbage collection is an automated process used to manage the runtime memory used by programs. Through this automation process, the JVM removes the overhead of programmers to allocate and free memory resources in the program.
Start Java garbage collection
As an automatic process, programmers do not need to start the garbage collection process displayed in the code. System.gc() and Runtime.gc() are used to request the JVM to start garbage collection.
Although this request mechanism provides programmers with an opportunity to start the GC process, the startup is the responsibility of the JVM. The JVM can reject this request, so there is no guarantee that all of these calls will perform garbage collection. The choice of startup timing is determined by the JVM and depends on whether the Eden area is available in the heap memory. The JVM leaves this choice to the implementation of the Java specification, and the specific algorithms used by different implementations are different.
Needless to say, we know that the garbage collection process cannot be enforced. I just found a scene where calling System.gc() makes sense. Through this article, let’s learn about the extreme situations that are suitable for calling System.gc() .
Java garbage collection process
Garbage collection is a process of reclaiming useless memory space and making it available to future instances.
Eden area: When an instance is created, it will first be stored in the Eden area of the young generation of heap memory.
Note: If you can't understand these words, I suggest you read this introduction to garbage collection, which provides a detailed introduction to memory models, JVM architectures, and these terms.
Survivor zones (S0 and S1): As part of the Young Generation GC (MinorGC) cycle, the surviving object (still referenced) is moved from the Eden zone to S0 of the Survivor zone. Similarly, the garbage collector scans S0 and moves the surviving instance into S1.
(Translator's Note: Don't the surviving people in Eden and S0 move to S1? Why do they move to S0 first and then from S0 to S1?)
An instance of death (no longer referenced) is marked as garbage collection. Depending on the garbage collector (there are four commonly used garbage collectors, which will be described in the next tutorial), either the tagged instances are constantly removed from memory, or the recycling process is completed in a separate process.
Older generation: Older generation is the second logical area in heap memory. When the garbage collector performs the MinorGC cycle, the surviving instance in the S1Survivor area will be promoted to the old age, while the unreferenced objects are marked as recycled.
Old GC (MajorGC): Compared with Java garbage collection process, old GC is the last stage of the instance life cycle. MajorGC scans the garbage recycling process of the elderly. If instances are no longer referenced, they are marked as recycled, otherwise they will continue to stay in the old age.
Memory shard: Once an instance is deleted from heap memory, its location becomes empty and can be used for allocation of future instances. These free spaces will fragment the entire memory area. For quick allocation of instances, defragmentation is required. Based on the different choices of the garbage collector, the recycled memory area is either constantly sorted out or completed in a separate GC process.
End of instances in garbage collection
Before freeing an instance and reclaiming memory space, the Java garbage collector calls the instance's respective finalize() method, so that the instance has the opportunity to free up the resources it holds. Although it is guaranteed that finalize() will be called before reclaiming memory space, there is no specified order and time. The order between multiple instances is unpredictable and may even occur in parallel. Programs should not pre-adjust the order between instances and recycle resources using the finalize() method.
Any exceptions that are not caught in the finalize process will be automatically ignored, and the finalize process of the instance is cancelled.
The JVM specification does not discuss the garbage collection mechanism for weak references, nor does it have clear requirements. The specific implementation is determined by the implementing party.
Garbage collection is done by a daemon thread.
When will the object meet the conditions for garbage collection?
All instances have no active thread access.
A circular reference instance that is not accessed by any other instance.
There are different reference types in Java. Determining whether an instance meets garbage collection conditions all depend on its reference type.
| Reference Type | Garbage collection |
|---|---|
| Strong Reference | Not in compliance with garbage collection |
| Soft Reference | Garbage collection may be performed, but will be a last resort |
| Weak Reference | Comply with garbage collection |
| Phantom Reference | Comply with garbage collection |
As an optimization technique during the compilation process, the Java compiler can choose to assign null values to instances, thereby marking the instance as recyclable.
class Animal { public static void main(String[] args) { Animal lion = new Animal(); System.out.println("Main is completed."); } protected void finalize() { System.out.println("Rest in Peace!"); }}In the above class, the lion object has never been used after instantiating the line. Therefore, as an optimization measure, the Java compiler can directly assign lion=null after instantiating the row. Therefore, the finalize function can print out 'RestinPeace!' even before SOP output. We cannot prove that this will happen because it depends on how the JVM is implemented and the memory used by runtime. However, we can learn one more: if the compiler sees that the instance will never be referenced in the future, it can select and free up instance space early.
There is a better example of when objects comply with garbage collection. All attributes of the instance can be stored in registers, which will then be accessed and read. Without exception, these values will be written back to the instance. Although these values can be used in the future, this instance can still be marked as compliant with garbage collection. This is a very classic example, isn’t it?
This is a very simple example that complies with garbage collection when assigned to null. Of course, complex situations can be like the above points. This is a choice made by the JVM implementer. The purpose is to leave the smallest memory footprint as possible, speed up response speed, and improve throughput. To achieve this, JVM implementers can choose a better solution or algorithm to reclaim memory space during the garbage collection process.
When the finalize() method is called, the JVM releases all synchronization locks on the thread.
GCScope sample program
Class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// No Object Is Eligible for GCt1.t = t2;// No Object Is Eligible for GCt2.t = t3;// No Object Is Eligible for GCt3.t = t1;// No Object Is Eligible for GCt1 = null;// No Object Is Eligible for GC (t3.t still has a reference to t1)t2 = null;// No Object Is Eligible for GC (t3.tt still has a reference to t2)t3 = null;// All the 3 Object Is Eligible for GC (None of them have a reference.// only the variable t of the objects are referring each other in a// rounded fashion forming the Island of objects with out any external// reference)}protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// No object complies with GCt1.t = t2;// No object complies with GCt2.t = t3;// No object complies with GCt3.t = t1;// No object complies with GCt1 = null;// No object complies with GC (t3.t still has a reference to t1)t2 = null;// No object complies with GC (t3.tt still has a reference to t2)t3 = null;// All three objects complies with GC (none of them has a reference. // Only the variable t of each object also points to each other, // Form a ring island composed of objects without any external references.)} protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}GC OutOfMemoryError sample program
GC does not guarantee the security of memory overflow problems, and careless code written down will cause OutOfMemoryError.
import java.util.LinkedList;import java.util.List;public class GC {public static void main(String[] main) {List l = new LinkedList();// Enter infinite loop which will add a String to the list: l on each// iteration.do {l.add(new String("Hello, World"));}while (true);}}Output:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.LinkedList.linkLast(LinkedList.java:142) at java.util.LinkedList.add(LinkedList.java:338) at com.javapapers.java.GCScope.main(GCScope.java:12)
Summarize
The above is the entire content of this article about briefly discussing the implementation process of Java garbage collection. I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!