JavaRush /Java 博客 /Random-ZH /有关 Java 中垃圾收集器的更多信息

有关 Java 中垃圾收集器的更多信息

已在 Random-ZH 群组中发布
你好!上一讲,我们首先熟悉了Java语言的内置机制——垃圾收集器。当您的程序运行时,它在后台运行,收集不再需要的对象,这些对象稍后将被删除。这样它就可以释放内存以供将来创建新对象。在本次讲座中,我们将仔细研究其工作原理。例如,某个对象如何以及在什么时候变得不再需要?垃圾收集器如何知道这一点?我们将回答这些问题:)我们的讲座更多的是概述:这些材料不需要记住。它的目的是拓宽您对内存和垃圾收集器工作的视野,因此阅读它并为自己学习新东西就足够了:) 让我们开始吧!您需要记住的第一件事是垃圾收集器与您的程序并行运行。它不是它的一部分,而是单独发挥作用:为了描述这一点,在上一讲中我们用机器人吸尘器进行了类比。事实上,情况并非总是如此。以前,垃圾收集器的设计方式是它与程序在同一线程中工作。根据某个时间表,它每隔几分钟就开始检查程序中是否存在不必要的对象。问题是,在这次检查和垃圾收集期间,程序冻结并且没有执行。想象一下您正坐在办公室里工作。但后来一位清洁女工来了,需要清洗房间里的地板。她把你从电脑后面踢了 5 分钟,你等着她打扫完。在此期间您无法工作。这大致就是垃圾收集器过去的工作方式:)后来,这种机制被改变了,现在垃圾收集器在后台工作,不会减慢程序本身的工作速度。您已经知道,当一个对象不再有任何引用时,该对象就会死亡。但垃圾收集器实际上并不计算对. 首先,它可能会很长。其次,效果不太好。毕竟,对象可以互相引用! 有关垃圾收集器的更多信息 - 2该图显示了一个示例,其中 3 个对象相互引用,但没有其他对象引用它们。也就是说,程序的其余部分不需要它们来运行。如果垃圾收集器只是简单地计算引用,那么所有这 3 个对象都将保留并且不会释放内存:有对它们的引用!它可以比作一艘宇宙飞船。在飞行过程中,宇航员决定检查维修备件清单,并在其中发现了一辆普通汽车的方向盘和踏板。显然这里不需要它们并且占用额外的空间。虽然这些部件是相互连接的并且具有一定的功能,但在航天器运行的框架内它们是不必要的垃圾,最好扔掉。因此,Java决定让垃圾回收的基础不计数引用,而是将对象分为两种类型——可达不可达。如何判断一个对象是否可达?一切巧妙的事情都很简单。如果一个对象被另一个可达对象引用,则该对象是可达的。这导致了“可达链”。它在程序启动时启动,并在其整个运行期间持续进行。看起来像这样: 有关垃圾收集器的更多信息 - 4图中的箭头表示我们程序的执行代码。在代码中,例如在 main() 方法中,创建对对象的引用。这些对象可以引用新对象,也可以引用更多对象,等等。形成了对象链接链。如果可以通过此链接链到达“根链接”(即在执行代码中直接创建的链接),则该对象被认为是可达的。在我们的图片中,它们以蓝色表示。但如果一个对象脱离了这条链,即当前正在执行的代码中没有一个变量包含对它的引用,也无法通过“链接链”到达它——它被认为是不可达的。在我们的程序中,两个这样的对象以红色表示。请注意:这些“红色”对象相互之间有链接。但是,正如我们之前所说,Java 中的现代垃圾收集器不进行引用计数。它确定对象是否可达不可达。因此,画面中的两个红色物体就会成为他的猎物。现在让我们从头到尾看一下整个过程,同时让我们看看Java中内存是如何工作的:) Java中的所有对象都存储在一个称为的特殊内存区域中。用普通语言来说,“堆”是指堆积如山的物体,其中所有东西都乱七八糟地散落在各处。但Java中的堆却不是这样的。它的结构非常有逻辑性和合理性。有一天,Java 程序员发现他们程序中的所有对象都可以分为两种类型 - 相对而言,简单对象“长寿”对象。“长寿”对象是那些在多次垃圾回收中幸存下来的对象。大多数情况下,它们将一直存在到程序结束。结果,存储所有创建的对象的公共堆被分为几个部分。第一部分有一个美丽的名字——Eden 圣经中的“伊甸园”)。这是一个很棒的名字,因为这是对象创建后的所在位置。当我们写入时,正是在这一部分为新对象分配内存new。可以创建许多对象,当该区域的空间耗尽时,第一个“快速”垃圾收集开始。必须说,垃圾收集器非常聪明,它根据堆中更多的内容(垃圾或工作对象)来选择工作算法。如果几乎所有对象都是垃圾,则收集器会标记“活动”对象并将它们移动到另一个内存区域,然后将当前区域完全清理干净。如果垃圾很少,并且大部分被活体占据,它就会标记垃圾,清理它,并安排剩余的对象。我们说“收集器标记“活动”对象并将它们移动到另一个内存位置”,但是是哪一个呢?至少在一次垃圾回收中幸存下来的所有对象都被转移的内存区域称为“生存空间”生存空间又分为世代。每个对象都会根据其经历的垃圾回收次数分配一个世代。如果有一个,则属于“第一代”,如果有 5 个,则属于“第五代”。伊甸园和生存空间一起形成一个称为年轻一代的区域。除了Young Generation之外,堆中还有另一个内存区域——Old Generation(“老年代”)。这些是在多次垃圾回收中幸存下来的非常长寿的对象。将它们与其他所有东西分开存放会更有利可图。并且只有当老一代区域已满时,即 即使程序中存在如此多的长寿命对象,导致内存不足,也会执行完整的垃圾收集。它不仅处理一个内存区域,而且通常处理 Java 机器创建的所有对象。当然,这需要更多的时间和资源。这就是为什么决定单独存储长寿命对象的原因。当其他区域的空间耗尽时,就会进行所谓的“快速垃圾收集”。它只覆盖一个区域,因此更经济、更快。最后,当百岁老人的区域也已经堵塞时,彻底的清理工作就开始了。因此,只有当不再需要时,组装人员才会使用最“重”的工具。示意性地讲,堆和清理的结构如下所示: 有关垃圾收集器的更多信息 - 5
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION