The last article introduced the relevant knowledge of the JVM memory model. In fact, there are some contents that can be introduced in more depth, such as dynamic insertion of constant pools at runtime, direct memory, etc. Later, I will take the time to improve the previous blog. Come today Introduce some garbage collection strategies in JVM.
1. The finishize() method When the object does not have any references, the object will usually be recycled, but what if we want to perform some operations before the object is recycled, such as closing some resources, or resurrecting the object to prevent it from being recycled? This is when the finalize method is used. The finailize method is a method defined in the Object class, which means that any object has this method. But this method will only be called once. If the object dies again after being resurrected, the finalize method will not be called when the object is recycled for the second time, and the priority is relatively low, and there is no guarantee that it will be executed. , so it is not recommended to use the finalize method. To sum up, there are 3 features: ①. GC was called before. ②. It will only be called once. ③. It is unreliable and cannot be guaranteed to be executed. It is not recommended to use
. Regarding how to use finalize, refer to the following code:1 public class FinalizeTest { 2 3 private static FinalizeTest test; 4 /** 5 * VM参数:-XX: +PrintGCDetails -Xmx=1M -Xms=1M 6 * 7 * @param args 8 */ 9 public static void main(String[] args) { 10 //先对test对象赋值 11 test = new FinalizeTest(); 12 int _1m = 1024 * 1024; 13 //将test置为null,便于回收 14 test = null; 15 try { 16 System.gc(); 17 //模拟睡眠5s,finalize优先级较低,保证finalize能执行 18 Thread.sleep(5000); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 if (test != null) { 23 System.out.println("first,i am alive"); 24 }else{ 25 System.out.println("first,i am dead"); 26 } 27 //由于test在finalize方法里复活了,再次将test置为null 28 test = null; 29 try { 30 System.gc(); 31 Thread.sleep(5000);//模拟睡眠5s,让GC回收 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 if (test != null) { 36 System.out.println("second,i am alive"); 37 }else{ 38 System.out.println("second,i am dead"); 39 } 40 41 } 42 @Override 43 protected void finalize() throws Throwable { 44 test = this ; 45 System.out.println("finalize excuted"); 46 super.finalize(); //调用父类的finailize方法 47 } 48 }
The result of running this code is as follows:
You can see, After the finalize method is executed, the test object is reactivated, so first, i am alive is printed. But during the second GC, the finalize method was not executed, so second, i am dead was printed. As mentioned earlier, finalize has low priority and is unreliable. If there is no Thread.sleep(5000), let’s look at the code and results:
1 public class FinalizeTest { 2 3 private static FinalizeTest test; 4 /** 5 * VM参数:-XX: +PrintGCDetails -Xmx=1M -Xms=1M 6 * 7 * @param args 8 */ 9 public static void main(String[] args) { 10 //先对test对象赋值 11 test = new FinalizeTest(); 12 int _1m = 1024 * 1024; 13 //将test置为null,便于回收 14 test = null; 15 try { 16 System.gc(); 17 //模拟睡眠5s,finalize优先级较低,保证finalize能执行 18 //不执行睡眠操作,Thread.sleep(5000); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 if (test != null) { 23 System.out.println("first,i am alive"); 24 }else{ 25 System.out.println("first,i am dead"); 26 } 27 //由于test在finalize方法里复活了,再次将test置为null 28 test = null; 29 try { 30 System.gc(); 31 //不执行睡眠操作,Thread.sleep(5000);//模拟睡眠5s,让GC回收 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 if (test != null) { 36 System.out.println("second,i am alive"); 37 }else{ 38 System.out.println("second,i am dead"); 39 } 40 41 } 42 @Override 43 protected void finalize() throws Throwable { 44 test = this ; 45 System.out.println("finalize excuted"); 46 super.finalize(); //调用父类的finailize方法 47 } 48 }
The running results are as follows:
It can be clearly seen here that the priority of the finalize method is relatively low.
Reflection on this example: The first piece of code in this example is implemented with reference to the code in "In-depth Understanding of Java Virtual Machine", but I always feel that there are two questions: Why is the test object modified with static Member variables exist? If it is static modification, then there is a method area, and the GC effect in the method area is usually not very good. The other one exists in the form of member variables, so that when finalize is recycled, it does not reflect the recycling of the current object itself, so I feel that this example is not very good.2. Reference counting method
The reference counting method is an earlier GC recycling algorithm. It is generally not used at present. Its main idea is Yes:
Each object maintains a reference counter, with an initial value of 0. When an object is referenced, the object's reference counter is incremented by 1. When it is not referenced, the object's reference counter is decremented. 1. If the reference counter of an object becomes 0, the object is considered recyclable. The advantages and disadvantages of using this method are obvious. The advantages are simple implementation and high efficiency. The disadvantage is that there may be circular references, leading to memory overflow.
3. Mark-clear method
Mark- The clearing method is divided into two stages: "marking" and "clearing" according to the name. The basic idea is: First mark all living objects. After the marking is completed, all marked objects are cleared uniformly. So how to determine whether an object can be recycled? During GC, the traversal starts from a series of GC Roots root nodes. The path traveled during the traversal is called the reference chain. If an object does not have any reference chain related to GC Roots, then the object is not available and will be judged as available. Recycling, this algorithm is also called the root search algorithm. So which objects can become GC Roots objects? In the Java language, the objects that can be used as GC Roots include the following four types: Reference variables in the virtual machine stack
Objects referenced by class static attributes in the method area Objects referenced by constants in the method areaThe object referenced by JNI (native method) in the local method stack
The algorithm diagram of the mark-and-clear method is as follows:
Note: This article The GC recycling algorithm picture is transferred from a netizen's article (click here). The content of the netizen's picture is also consistent with the original work, but the color is different.
4. Copying method of the new generation
The basic idea of the copying method is: Divide the memory into 2 blocks of equal size , only use one of them at a time, copy all surviving objects to another area each time during GC, and then clean up the memory.
These are all reference objects in the method area and stack. The advantages of the copy method are: simple implementation, fast recycling, and no memory fragmentation. However, since only one of them is used at a time, the memory utilization is low. The schematic diagram of the replication algorithm is as follows:
Related recommendations:
jvm garbage collection algorithm
Share Java garbage collection mechanism learning summary
The above is the detailed content of JAVA virtual machine study notes: Garbage collection method in JVM memory model. For more information, please follow other related articles on the PHP Chinese website!