Java Garbage Collection with Programming Examples
Table of Contents
Java Garbage Collection:
Java Garbage Collection- Programmers know the importance of “initialization”, but usually forget the importance of cleanup. After all, who needs to clear an int? But for libraries, it is not always safe to simply “release” an object after use. Of course, Java can use the java garbage collector can reclaim pairs that are no longer used. The memory occupied by the elephant. Now consider a very special and rare situation. Suppose our object is allocated a “special” memory area, no There is use new. The java garbage collector only knows to release the memory allocated by new, so it does not know how to release the “special” memory of the object. For To solve this problem, Java provides a method called finalize(), which can be defined for our class. Ideally, it works for It should be like this: Once the java garbage collector is ready to release the storage space occupied by the object, it first calls finalize(), and only after During a java garbage collection process, the memory of the object will be reclaimed. So if finalize() is used, one can be performed during garbage collection. Some important removal or cleaning work.
But it is also a potential programming trap, because some programmers (especially those with a C++ development background) may mistakenly think that it is The finalize() used in C++ for the “Destructor”-when destroying (clearing) an object, this will definitely be called function. But here it is necessary to distinguish the difference between C++ and Java, because C++ objects will definitely be cleared (to eliminate the cause of programming errors) However, Java objects are not necessarily “collected” as garbage. Or in other words:
Java garbage collection does not mean “destroy”!
If you keep this in mind at all times, the possibility of stepping on the trap will be greatly reduced. It means some actions before we no longer need an object It must be taken, and these actions must be taken by oneself. Java does not provide a “destroyer” or similar concept, so it must be created A primitive method, use it to perform this kind of removal. For example, suppose that during the object creation process, it will draw itself onto the screen. if not Clearly delete its image from the screen, then it may never be cleared. If a certain deletion mechanism is placed in finalize(), then suppose The object is taken away as garbage, and the image first removes itself from the screen. But if it is not collected, the image will remain. So remember The second important point is:
Our objects may not be collected as garbage!
Sometimes you may find that the storage space of an object will never be released, because your program is always close to the critical point of running out of space. The sequence execution ends, and the java garbage collector has not released the storage space of any objects we created. Then as the program exits, those resources The source is returned to the operating system. This is a good thing, because java garbage collection itself also consumes some overhead. If you never use it, then forever There is no need to spend this part of the expenses.
Amazon Purchase Links:
*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!
What is the purpose of finalize():
At this point, you may have believed that you should use finalize() as a general-purpose cleanup method. What are its benefits? The third important point to remember is:
Java garbage collection is only about memory!
In other words, the only reason the java garbage collector exists is to reclaim memory that is no longer used by the program. So for any activity related to java garbage collection In motion, the most notable of these is the finalize() method, which must also be related to memory and its recovery.
But does this mean that if the object contains other objects, finalize() should explicitly release those objects? The answer is no-garbage The collector will be responsible for releasing the memory occupied by all objects, no matter how these objects are created. It limits the need for finalize() to special Case. In this case, our object can allocate some storage space in a different way than when creating the object. But you may notice Now, everything in Java is an object, so what is going on here?
The reason for using finalize() seems to be because sometimes it is necessary to take a method different from the normal method of Java, by assigning Memory to do some C-style things. This can be done mainly through “intrinsic methods”, which call non-Java methods from Java One way (the inherent method is discussed in Appendix A). C and C++ are the only languages currently supported by inherent methods. But because they can adjust With subroutines written in other languages, it can effectively call anything. In non-Java code, you may be able to call C .
The malloc() series of functions use it to allocate storage space. And unless free() is called, the storage space will not be released, resulting in internal The emergence of “loopholes”. Of course, free() is a C and C++ function, so we need to use an inherent method inside finalize() Call it.
After reading the above text, you may have figured out that you don’t need to use finalize() too much. This idea is correct; it is not The ideal place for general cleaning work. So, where should ordinary removal work be carried out?
Cleanup must be performed:
In order to clean an object, the user of that object must call a cleanup method at the place where the cleanup is desired. This sounds easy to do However, it conflicts slightly with the concept of C++ “destroyer”. In C++, all objects are destroyed (cleared). Or in other words, all pairs The elephants “should” be destroyed. If the C++ object is created as a local object, such as in the stack (which is impossible in Java), then Cleanup or destruction will be done at the end of the scope represented by the “closing brace” that created the object. If the object is created with new (Similar to Java), then when the programmer calls the delete command of C++ (Java does not have this command), the corresponding destroy Device. If the programmer forgets, then the destroyer will never be called, and we will end up with a memory “hole”, including objects The other parts will never be cleared.
On the contrary, Java does not allow us to create local (local) objects-use new anyway. But in Java, there is no “delete” command Order to release the object, because the java garbage collector will help us automatically release the storage space. So if we take a more simplified standpoint, we can say It is precisely because of the java garbage collection mechanism that Java does not have a destroyer. However, as you learn more in the future, you will know the memory of the java garbage collector. This does not completely eliminate the need for the destructor, or the need for the mechanism represented by the destructor (and definitely not directly adjust Use finalize(), so try to avoid using it). If you want to perform some form of cleanup work other than freeing up storage space, still A method in Java must be called. It is equivalent to the C++ destroyer, but not as convenient as the latter.
One of the most useful aspects of finalize() is to observe the garbage collection process. The following example shows everyone the experience of java garbage collection, and summarized the previous statement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
//: Garbage.java // Demonstration of the garbage // collector and finalization class Chair { static boolean gcrun = false; static boolean f = false; static int created = 0; static int finalized = 0; int i; Chair() { i = ++created; if(created == 47) System.out.println("Created 47"); } protected void finalize() { if(!gcrun) { gcrun = true; System.out.println( "Beginning to finalize after "+ created + "Chairs have been created"); } if(i == 47) { System.out.println( "Finalizing Chair #47, "+ "Setting flag to stop Chair creation"); f = true; } finalized++; if(finalized >= created) System.out.println("All "+ finalized +" finalized"); } } public class Garbage { public static void main(String[] args) { if(args.length == 0) { System.err.println("Usage: \n" + "java Garbage before\n or:\n" + "java Garbage after"); return; } while(!Chair.f) { new Chair(); new String("To take up space"); } System.out.println( "After all Chairs have been created:\n" + "total created = "+ Chair.created + ", total finalized = "+ Chair.finalized); if(args[0].equals("before")) { System.out.println("gc():"); System.gc(); System.out.println("runFinalization():"); System.runFinalization(); } System.out.println("bye!"); if(args[0].equals("after")) System.runFinalizersOnExit(true); } } ///:~ |
The above program created many Chair objects, and at some point after the java garbage collector started running, the program would stop creating Chair.
Since the java garbage collector may run at any time, we cannot know exactly when it started. Therefore, the program uses a program called gcrun To indicate whether the java garbage collector has started running. Using the second flag f, Chair can tell main() that it should stop the to make. Both of these flags are set inside finalize(), which is called during java garbage collection.
The other two static variables-created and finalized-are used to track the number of objects created and the java garbage collector has performed, respectively The number of objects for finishing work. Finally, each Chair has its own (non-static) int i, so you can track and understand its specific editing What is the number. After the chair number 47 finishes the finishing work, the mark will be set to true, and finally the creation process of the Chair object is ended. All of this is done inside main() in the following loop:
while(!Chair.f) {
new Chair();
new String(“To take up space”);
}
You may be wondering when this loop will stop because there is no statement to change the value of Chair.f inside. However, finalize() The process will change this value until finally the object number 47 is finished.
The String object created during each cycle is just extra garbage, which is used to attract the java garbage collector once the garbage collector is available If you feel “nervous” about the storage capacity, you will start paying attention to it.
When running this program, a command line argument “before” or “after” is provided. Among them, the “before” argument will be called The System.gc() method (forces the garbage collector), and also calls the System.runFinalization() method for finishing jobs. These methods are all available in Java 1.0, but the runFinalizersOnExit() method called by using the “after” argument However, only Java 1.1 and subsequent versions provide support for it. Note that this method can be called at any time during program execution, And the execution of the finishing program has nothing to do with whether the java garbage collector is running.
Note: Unfortunately, the java garbage collector scheme adopted by Java 1.0 can never call finalize() correctly. Therefore, the finalize() method (Especially those used to close files) in fact are often not called. Now some articles claim that all closing modules will be exited in the program Called when it exits-even when the program is terminated, the java garbage collector has not taken action on those objects. This is not true love Circumstances, so we cannot expect finalize() to be called for all objects. In particular, finalize() has almost nothing in Java 1.0 usefulness.
The previous program reveals to us: In Java 1.1, the promise that the closing module will definitely run has become a reality-but only if we are clear To force it to take this action. If an argument other than “before” or “after” (such as “none”) is used, then two finishing touches Nothing will happen, and we will get output like the following:
Created 47
Beginning to finalize after 8694 Chairs have been created
Finalizing Chair #47, Setting flag to stop Chair creation
After all Chairs have been created:
total created = 9834, total finalized = 108
bye!
Therefore, by the end of the program, not all closing modules will be called. To force the finishing work, you can call System.gc(), then call System.runFinalization(). This will clear all objects that have not been used so far. Do this one A slightly strange place is to call gc() before calling runFinalization(), which seems to contradict Sun’s documentation. Touch, it claims to run the finishing block first, and then release the storage space. However, if runFinalization() is called first, then gc(), the closing module will not be executed at all.
For all objects, the reason why Java 1.1 sometimes defaults to skip finishing work is because it thinks it is too expensive. No matter what Methods that force java garbage collection may notice a longer time delay than when there is no additional finishing work.
Example: How to make student record use java Garbage collection:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
class Student { private int roll_number; private String stu_name; private int stu_age; private static int nextId=1; public Student(String name,int age) { this.stu_name = name; this.stu_age = age; this.roll_number = nextId++; } public void show() { System.out.println ("rollNo="+roll_number+"\nStudent Name="+stu_name+"\nStudent Age="+stu_age); } public void showNextId() { System.out.println ("Next Student RollNo will be="+nextId); } } class Garbage { public static void main(String []args) { Student a=new Student("Fawad khan",26); Student b=new Student("shaista",25); Student c=new Student("xyz3",25); a.show(); b.show(); c.show(); a.showNextId(); b.showNextId(); c.showNextId(); { Student X=new Student("xyz4",23); Student Y=new Student("xyz5",21); X.show(); Y.show(); X.showNextId(); Y.showNextId(); } a.showNextId();//Output of this line } } |