Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java—垃圾收集器如何快速知道哪些对象不再有对它们的引用?_Java_Memory_Garbage Collection - Fatal编程技术网

java—垃圾收集器如何快速知道哪些对象不再有对它们的引用?

java—垃圾收集器如何快速知道哪些对象不再有对它们的引用?,java,memory,garbage-collection,Java,Memory,Garbage Collection,我知道在Java中,如果一个对象不再有任何对它的引用,垃圾收集器会在一段时间后将其回收回来 但是,垃圾收集器如何知道对象有或没有关联的引用呢 垃圾收集器是否使用某种hashmap或表 编辑: 请注意,我不是在问gc的工作原理。真的,我不是这样问的 我要问的是,gc如何高效地知道哪些对象是活的,哪些是死的 这就是为什么我在我的问题中说gc需要维护某种hashmap或set,并持续更新对象的引用数?典型的现代JVM使用几种不同类型的垃圾收集器 一种类型通常用于已经存在一段时间的对象,称为。它基本上

我知道在Java中,如果一个对象不再有任何对它的引用,垃圾收集器会在一段时间后将其回收回来

但是,垃圾收集器如何知道对象有或没有关联的引用呢

垃圾收集器是否使用某种hashmap或表


编辑:

请注意,我不是在问gc的工作原理。真的,我不是这样问的

我要问的是,gc如何高效地知道哪些对象是活的,哪些是死的


这就是为什么我在我的问题中说gc需要维护某种hashmap或set,并持续更新对象的引用数?

典型的现代JVM使用几种不同类型的垃圾收集器

一种类型通常用于已经存在一段时间的对象,称为。它基本上涉及从已知的“活动”对象(所谓的垃圾收集根)开始,跟踪所有对象引用链,并将每个可访问对象标记为“活动”

完成此操作后,扫描阶段可以回收那些尚未标记为“活动”的对象


为了让这个过程正常工作,JVM必须知道每个对象引用在内存中的位置。这是垃圾收集器成为垃圾收集器的必要条件(Java就是这样)。

GC将知道可以尽快删除对象。您不需要管理此过程


但是您可以非常礼貌地要求GC使用
System.GC()
运行。这只是对系统的提示。GC不必在那一刻运行,它不必删除您的特定对象等。因为GC是大老板,而我们(Java程序员)只是它的奴隶…:(

Java有各种不同的垃圾收集策略,但它们基本上都是通过跟踪哪些对象可以从已知的活动对象访问来工作的

文章中有一个很好的总结,但是对于真正的细节,你应该看看

当运行程序中的任何指针都无法再访问某个对象时,该对象被视为垃圾。最简单的垃圾收集算法只是对每个可访问对象进行迭代。剩余的任何对象都被视为垃圾。此方法所用的时间与活动对象的数量成正比,即prohibitive适用于维护大量实时数据的大型应用程序

从J2SE平台1.2版开始,虚拟机合并了许多不同的垃圾收集算法,这些算法使用分代收集进行组合。虽然naive garbage collection检查堆中的每个活动对象,但分代收集利用了大多数应用程序的几个经验观察到的属性o避免额外工作

这些观察到的特性中最重要的是婴儿死亡率

也就是说,像迭代器这样的许多对象只存在很短的时间,因此较年轻的对象比较老的对象更有可能进行垃圾收集

有关更多最新的调整指南,请参阅:

  • (JavaSE8)
顺便说一句,请注意不要猜测您的垃圾收集策略,我知道许多程序的性能会因为过度使用
System.gc()而受到影响
或不适当的
-XX
选项。

没有有效的方法-它仍然需要遍历堆,但有一种黑客方法:将堆划分为更小的部分(因此无需扫描整个堆)。这就是为什么我们有分代垃圾收集器,以便扫描花费更少的时间

当您的整个应用程序停止并且您可以分析对象图时,这相对来说是“容易”回答的。这一切都是从
GC根开始的(我将让您找到这些根的文档),但基本上这些根不是由
GC
收集的

从这里开始进行特定扫描,分析“活动”对象:与这些根有直接(或传递)连接的对象,因此不可回收。在图论中,这称为“颜色/遍历”使用3种颜色:黑色、灰色和白色创建图形。
白色表示它没有连接到根,
灰色表示它的子图还没有被遍历,
黑色表示被遍历并连接到根。因此,基本上要知道现在到底什么是死的/活的-只需获取所有白色的堆即可最初,将其涂成黑色。
白色
的所有东西都是垃圾。有趣的是,
GC
通过知道什么是实际存在的来识别“垃圾”。例如,有一些图形可以将其可视化

但这是一个简单的场景:当你的应用程序完全停止时(有时几秒钟),你可以扫描堆。这叫做
STW
-停止世界事件,人们通常讨厌这些。这就是并行收集器所做的:停止一切,做GC必须做的任何事情(包括查找垃圾),然后让应用程序线程启动

当你的应用程序正在运行并且正在扫描堆时会发生什么情况?
并发地扫描堆?
G1/CMS
这样做。想想看:当你的应用程序可以通过不同的线程更改某个叶时,你如何解释某个图中的叶是否处于活动状态

例如,
Shenandoah
通过“截取”图形上的更改来解决此问题。当与应用程序同时运行时,它将捕获所有更改并将这些更改插入一些线程本地特殊队列,称为
SATB队列
(乞讨队列的快照);而不是直接更改堆。完成后,将发生一个非常短的
STW
事件,这些队列将