“嗨!我决定再给你上一堂关于垃圾回收的小课。”
正如您已经知道的那样,Java 机器本身会监视一个对象何时变得不需要,并将其删除。
“是的,之前你和Rishi跟我说过,具体的我不记得了。”
“好吧。那我们再说一遍。”
“一旦创建了一个对象,JVM 就会为它分配内存。使用引用变量监视对象的兴趣。 可以在垃圾收集期间删除一个对象,即如果没有变量引用该对象,则释放内存的过程对象。 ”
“告诉我一些关于垃圾收集器的信息——它是什么以及它是如何工作的。”
“好吧。过去垃圾收集发生在主线程上。每 5 分钟一次,或更频繁。如果没有足够的可用内存,Java 机器将挂起所有线程并删除未使用的对象。”
“但这种方法现在已经被放弃了。下一代垃圾收集器在幕后和一个单独的线程上工作。这被称为并发垃圾收集。”
“我明白了。删除或不删除对象的决定究竟是如何做出的?”
“仅仅计算对一个对象的引用次数并不是很有效——可能有一些对象相互引用,但没有被其他对象引用。”
”所以Java采取了不同的方法。Java 将对象分为可达和不可达。 如果一个对象被另一个可达(活)对象引用,则该对象是可达(活着)。可达性由线程决定。运行线程总是被认为是可达(活着) ,即使没有人提及它们。”
“好的。我想我明白了。”
“实际的垃圾收集是如何发生的——删除不需要的对象?”
“很简单。在 Java 中,内存按照惯例被分成两部分,当垃圾回收的时候,所有活着的(可达的)对象被复制到另一部分内存中,旧的内存全部被释放。”
“这是一种有趣的方法。无需计算引用:复制所有可达的对象,其他一切都是垃圾。”
“它比那要复杂一点。Java 程序员发现对象通常分为两类:长寿命的(在程序运行的整个过程中都存在)和短寿命的(在方法中和执行 «local » 操作)。
“将长寿命物体与短寿命物体分开会更有效率。为此,有必要想出一种方法来确定物体的寿命。”
“所以,他们把所有的内存都分成了«generations»。有第一代对象,第二代对象等。每次清除内存时,generation counter加1。如果某些对象存在多代,那么它们被记录为长寿。”
“今天,垃圾收集器是 Java 中一个非常复杂和高效的部分。它的许多部分都以启发式的方式工作——基于进行猜测的算法。结果,它经常“不听”用户的意见。”
“意义?”
“Java 有一个垃圾收集器 ( GC ) 对象,可以使用System.gc () 方法调用。”
“您还可以使用System.runFinalization()强制调用要删除的对象的终结方法。但事实是,根据 Java 文档,这既不保证垃圾收集将开始,也不保证终结( ) 方法将被调用。 垃圾收集器决定何时调用它以及调用什么。 ”
“哇!很高兴知道。”
“但还有更多。如您所知,在 Java 中,一些对象引用其他对象。这种引用网络用于确定是否应删除一个对象。”
“而且,你看。Java 有特殊的引用,可以让你影响这个过程。它们有特殊的包装类。它们在这里:”
“ SoftReference 是软引用。”
“ WeakReference 是弱引用。”
“ PhantomReference是一个虚引用。”
“呃……这让我想起了内部类、嵌套类、嵌套匿名类、局部类,名字不一样,但完全搞不清楚是干什么用的。”
“说,阿米戈,你已经成为一名程序员。现在你因为类名而生气,说 «它们没有提供足够的信息,而且不可能用一个名字(!)来确定这个类做什么,如何,以及为什么»。
“哇。我都没注意到。但它是如此明显。”
“好的。废话不多说了。让我告诉你有关 SoftReferences 的事。”
“这些引用是专门为缓存而设计的,尽管它们可以用于其他目的——完全由程序员自行决定。”
“这是此类参考的示例:”
// 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();
“如果对一个对象的唯一引用是软的,那么它会继续存在并被称为‘软可达’。”
“但是! 如果程序没有足够的内存,垃圾收集器可以删除仅由软引用引用的对象。 如果程序突然没有足够的内存,在抛出 OutOfMemoryException 之前,垃圾收集器将删除所有对象被软引用引用并将再次尝试为程序分配内存。”
“假设客户端程序经常向服务器程序请求各种数据。服务器程序可以使用软引用来缓存其中的一些数据。如果通过软引用免于死亡的对象占用了大部分内存,那么垃圾收集器会简单地删除它们一切。它很漂亮!
“嗯。我自己也喜欢。”
“嗯,一个小补充:SoftReference类有两个方法。get() 方法返回SoftReference引用的对象。如果对象被垃圾收集器删除,get () 方法将突然开始返回 null。”
“用户也可以通过调用 clear() 方法显式清除SoftReference 。在这种情况下, SoftReference对象内部的弱链接将被破坏。”
“目前为止就这样了。”
“谢谢你的有趣故事,艾莉。真的很有趣。”
GO TO FULL VERSION