"Hi! I decided to give you another small lesson about garbage collection."
As you already know, the Java machine itself monitors when an object becomes unnecessary, and deletes it.
"Yep. You and Rishi told me about it earlier. I don't remember the details."
"OK. Then let's go over it again."
"As soon as an object is created, the JVM allocates memory for it. Interest in the object is monitored using reference variables. An object can be deleted during garbage collection, i.e. the procedure by which memory is released if there are no variables referencing the object."
"Tell me a little about the garbage collector—what it is and how it works."
"OK. Garbage collection used to happen on the main thread. Every 5 minutes, or more often. If there was ever not enough free memory, the Java machine would suspend all threads and delete unused objects."
"But this approach has been abandoned now. The next-gen garbage collector works behind the scenes and on a separate thread. This is called concurrent garbage collection."
"I see. How exactly is the decision to delete an object or not made?"
"Just counting the number of references to an object is not very effective—there may be objects that reference each other, but are referenced by no other objects."
"So Java takes a different approach. Java divides objects into reachable and unreachable. An object is reachable (alive) if it is referenced by another reachable (living) object. Reachability is determined from threads. Running threads are always considered reachable (alive), even if nobody references them."
"OK. I think I get it."
"How does the actual garbage collection happen—the deletion of unnecessary objects?"
"It's simple. In Java, memory is divided into two parts by convention, and when it's time for garbage collection, all living (reachable) objects are copied to another part of the memory, and the old memory is all released."
"That's an interesting approach. No need to count references: copy all the reachable objects, and everything else is garbage."
"It's a bit more complicated than that. Java programmers found that objects are usually divided into two categories: long-lived (which exist the entire time the program is running) and short-lived (which are needed in methods and for performing «local» operations)."
"It's much more efficient to keep long-lived objects separate from short-lived ones. To do this, it was necessary to come up with a way to determine the longevity of the object."
"So, they divided all memory into «generations». There are first-generation objects, second-generation objects, etc. Each time memory is cleared, the generation counter is incremented by 1. If certain objects exist in multiple generations, then they are recorded as long-lived."
"Today, the garbage collector is a very complex and efficient part of Java. Many of its parts work heuristically—based on algorithms that make guesses. As a result, it often «doesn't listen to» the user."
"Java has a garbage collector (GC) object that can be called using the System.gc() method."
"You can also use System.runFinalization() to force calls to the finalize methods of the objects to be deleted. But the fact is that, according to the Java documentation, this guarantee neither that garbage collection will start, nor that the finalize() method will be called. The garbage collector decides when to call it and on what."
"Whoa! Good to know."
"But there's more. As you know, in Java, some objects reference others. This network of references is used to determine whether an object should be deleted."
"And, look. Java has special references that let you influence this process. There are special wrapper classes for them. Here they are:"
"SoftReference is a soft reference."
"WeakReference is a weak reference."
"PhantomReference is a phantom reference."
"Uh... This reminds me of inner classes, nested classes, nested anonymous classes, and local classes. The names are different, but it's not at all clear what they are for."
"Say, Amigo, you've become a programmer. Now you're angry because of the class names, saying «they aren't informative enough, and it's impossible with one name(!) to determine what this class does, how, and why»."
"Wow. I didn't even notice. But it's so obvious."
"OK. Enough words. Let me tell you about SoftReferences."
"These references were specifically designed for caching, though they can be used for other purposes—all at the discretion of the programmer."
"Here's an example of such a reference:"
// Create a Cat object Cat cat = new Cat(); // Create a soft reference to a Cat object SoftReference<Cat> catRef = new SoftReference<Cat>(cat); // Now only the catRef soft reference points at the object cat = null; // Now the ordinary cat variable also references the object cat = catRef.get(); // Clear the soft reference catRef.clear();
"If the only references to an object are soft, then it continues to live and is called 'softly-reachable'."
"But! An object referenced only by soft references can be deleted by the garbage collector if the program doesn't have enough memory. If suddenly the program doesn't have enough memory, before throwing an OutOfMemoryException, the garbage collector will delete all objects referenced by soft references and will try again to allocate memory to the program."
"Suppose a client program frequently requests various data from a server program. The server program can use a SoftReference to cache some of it. If objects kept from death by soft references take up a large part of memory, then the garbage collector simply deletes them all. It's beautiful!"
"Yeah. I liked it myself."
"Well, one small addition: The SoftReference class has two methods. The get() method returns the object referenced by the SoftReference. If the object was deleted by the garbage collector, the get() method will suddenly start returning null."
"The user can also clear the SoftReference explicitly by calling the clear() method. In this case, the weak link inside the SoftReference object will be destroyed."
"That's all for now."
"Thanks for the interesting story, Ellie. It really was very interesting."