CodeGym /Java 博客 /随机的 /关于垃圾收集器的更多信息
John Squirrels
第 41 级
San Francisco

关于垃圾收集器的更多信息

已在 随机的 群组中发布
你好!在上节课中,我们首先熟悉了Java内置的垃圾收集器,并大致了解了它的工作原理。它在您的程序运行时在后台工作,收集稍后将被删除的不必要的对象。因此,它释放了可用于在将来创建新对象的内存。
关于垃圾收集器的更多信息 - 1
在本课中,我们将更详细地讨论它是如何工作的。例如,一个对象如何以及何时变得不必要?垃圾收集器如何发现?这些是我们将在今天的课程中回答的问题 :) 本课程将更像是一个概述:您不需要死记硬背这些材料。目的主要是扩展您对内存和垃圾收集器工作原理的了解,所以请通读并为自己找到新的东西:) 让我们开始吧!您需要记住的第一件事是垃圾收集器与您的程序并行工作. 它不是您程序的一部分。它单独运行(在上一课中,我们将其与机器人真空吸尘器进行了比较)但并非总是如此。过去,垃圾收集是在与您的程序相同的线程上执行的。按照某个时间表(每隔几分钟一次),垃圾收集器将检查程序中是否存在不需要的对象。问题是程序会在检查和垃圾收集期间挂起(不执行)。想象一下,您正坐在办公室里工作。但随后清洁女工进来清洗地板。她让你离开电脑 5 分钟,然后你等到她打扫完。在此期间,您无法工作。这就是垃圾收集器过去的工作方式 :) 这种机制后来发生了变化,现在垃圾收集器在后台运行,不妨碍程序本身的工作。你已经知道当一个对象不再有引用时它就会死亡。事实上,垃圾收集器不计算对象引用。首先,这可能需要很长时间。其次,它不是很有效。毕竟,对象可以相互引用! 关于垃圾收集器的更多信息 - 2该图显示了一个示例,其中 3 个对象相互引用,但没有其他对象引用它们。换句话说,程序的其余部分不需要它们。如果垃圾收集器只是简单地计算引用,这 3 个对象将不会被收集,内存也不会被释放(它们有引用!)。我们可以将其比作航天器。在飞行过程中,宇航员决定检查可用于维修的备件清单。除其他外,他们从一辆普通汽车上找到了方向盘和踏板。显然,这里不需要它们并且不必要地占用空间(尽管这两个部分相互关联并具有某些功能)。但在飞船内部,它们是应该丢弃的无用垃圾。因此,在 Java 中,决定收集垃圾不是基于引用计数,可达不可达。我们如何确定一个对象是否可达?这一切都非常巧妙。如果一个对象被另一个可达对象引用,则该对象是可达的。因此,我们得到了“可达链”。它在程序启动时开始,并在程序持续期间持续。它看起来像这样: 关于垃圾收集器的更多信息 - 3 图中的箭头表示我们程序的可执行代码。代码(例如,main()方法)创建对对象的引用。这些对象可以引用其他对象,这些对象可以引用其他对象,等等。这样就形成了一个引用链. 如果您可以从一个对象追踪到“根引用”(直接在可执行代码中创建的引用),那么它就被认为是可达的。此类对象在图片中标记为黑色。但是如果一个对象掉出这个链,那么这个对象就是不可达的,即当前正在执行的代码中没有任何变量引用它,并且不能通过“引用链”到达它。在我们的程序中,两个这样的对象被标记为红色。请注意,这些“红色”对象相互引用。但正如我们之前所说,Java 的现代垃圾收集器不计算引用。判断一个对象是可达还是不可达. 结果,它会抓住图中的两个红色物体。现在让我们从头到尾看一下整个过程。这样做时,我们还将了解 Java 中的内存是如何安排的:) 所有 Java 对象都存储在称为堆的特殊内存区域中。在日常用语中,堆通常是一堆物品,所有东西都混杂在一起。但这不是 Java 中的堆。它的结构非常符合逻辑和合理性。 在某些时候,Java 程序员发现他们所有的对象都可以分为两种类型:简单对象“长寿命对象”. “长寿命对象”是在多轮垃圾收集中幸存下来的对象。他们通常会一直活到节目结束。最后,存储所有对象的完整堆被分成几个部分。第一部分有一个美丽的名字:伊甸园(来自圣经中的“伊甸园”)。这个名字很合适,因为这是对象在创建后结束的地方。这是我们使用关键字 new 时创建新对象的内存部分。可能会创建很多对象。当这个区域空间不足时,初始的“快速”垃圾收集就开始了。不得不说垃圾收集器非常聪明。它根据堆中是否有更多垃圾或更多活动对象来选择一种算法。如果几乎所有对象都是垃圾,收集器会标记活动对象并将它们移动到另一个内存区域。那么当前区域就彻底清空了。如果垃圾不是很多,并且堆中大部分是活动对象,收集器会标记垃圾,将其清除,然后将其他对象打包在一起。我们说 ”一个生存空间一个生存空间,又分为几代人。每个对象都属于一个特定的世代,这取决于它在多少轮垃圾收集中幸存下来。如果一个对象在一轮垃圾收集中幸存下来,那么它就在“第一代”;如果是 5,则为“第 5 代”。eden 和一个生存空间共同组成了一个区域,叫做新生代。除了新生代之外,堆中还有一块内存区域叫做老年代. 这正是经过多轮垃圾收集后存活下来的长寿命对象所在的区域。将它们与所有其他的分开是有好处的。全量垃圾回收只有在老年代已满时才执行,即程序中长寿命对象太多,内存不够用。这一过程涉及多个内存区域。一般来说,它涉及Java机器创建的所有对象。当然,这需要更多的时间和资源。这正是单独存储长寿命对象的决定。“快速垃圾回收”是在其他区域空间不足时进行的。这只涉及一个领域,因此速度更快,效率更高。最后,当长寿命对象的区域也被完全填满时,触发完整的垃圾收集。因此,收藏家只有在无法避免时才使用“最重”的工具。这是堆结构和垃圾收集的可视化表示: 关于垃圾收集器的更多信息 - 4
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION