当垃圾收集器消除了对象后,该对象会去哪儿?

Bhr*_*ugs 2 java garbage-collection

假设垃圾收集器已识别出一个类(对象)的实例-Java程序未使用该实例。因此,垃圾回收器决定消除该对象,因为该对象未在代码中的任何地方使用。现在,当消除对象时,该对象在内存中的位置在哪里?内存中的那个对象实际上发生了什么?一般而言-当消除对象时-计算机如何处理消除?如何消除?

我的问题更多是关于-消除堆中的对象发生后会发生什么。(在Java中)

我能想到的事情很少是:该对象(在堆内)的内存现在变为空闲,但是该对象仍保留在系统中,并且由于内存可用,因此新创建的对象可以占用其空间。因此,如果我以二进制格式考虑:先前对象的1和0将被新的1和0(新对象)序列覆盖。

在您的答案中,请以以下格式提供答案:

  1. 垃圾收集对象实际上发生了什么?
  2. 用Java或计算机科学术语称呼这些过程的名称是什么?

注意:我试图在stackoverflow上找到类似的问题/答案,但是这个问题是特定的,因此我找不到答案,因此我不得不发布一个问题。

Gho*_*ica 5

没发生什么事。

对象并不是真正的“生命体”。最后,它只是:内存中的字节。JVM保留了一些信息:“此对象为'alive'”(供其他活动对象使用),以及“此处为该对象的内存”。

现在,当GC“收集”该对象时,从概念上发生了什么:JVM只是从其内部数据结构中删除了“我在这里放有内存的对象”。最有可能的是,诸如“地址y处的x字节的已释放内存”之类的信息存储在JVM中的其他数据结构中。这样JVM就会知道:先前已占用的内存现在可用于将其重新用于另一个对象。

这很可能导致:该内存位置位于那儿,相当长一段时间没有变化。直到JVM需要更多内存,并决定出于其他目的重新使用该“空间”。


Hol*_*ger 5

您被常用术语 \xe2\x80\x9cgarbagecollector\xe2\x80\x9d 误导了,这是一个用词不当。\xe2\x80\x9c 垃圾收集器\xe2\x80\x9d 不收集垃圾。

\n\n

所以你的问题是从错误的前提开始的:

\n\n
\n

假设垃圾收集器已识别出一个类(对象)的实例 - Java 程序未使用该实例。因此,垃圾收集器决定消除该对象,因为它没有在代码中的任何地方使用。

\n
\n\n

这两件事都不会发生。垃圾收集器不会识别单个未使用的对象,并且它不会\xe2\x80\x99t \xe2\x80\x9cdestroy\xe2\x80\x9d任何对象,因为对象的销毁不是一件事。

\n\n

垃圾收集器的工作原理是确定哪些对象仍在使用中,通常是从根集开始遍历所有对象引用,即仍在运行的线程的局部变量和引导加载程序加载的类的静态字段。

\n\n

当它知道哪些对象仍在使用时,这些对象之间的间隙就是可回收的内存,无论之前存储了多少对象。它可能只是将这些内存块添加到可用内存列表中,但大多数现代垃圾收集器将重新定位仍在使用的对象,以获得连续的可用内存块,以实现快速分配并防止碎片。

\n\n

所以

\n\n
\n
    \n
  1. 垃圾收集对象实际上发生了什么?
  2. \n
\n
\n\n

\xe2\x80\x9ccollected\xe2\x80\x9d 对象没有任何反应。死亡对象与进程完全无关。

\n\n
\n
    \n
  1. 这些进程在 Java 或计算机科学术语中的名称是什么?
  2. \n
\n
\n\n

通用术语仍然是\xe2\x80\x9c垃圾收集\xe2\x80\x9d,即使它的字面含义\xe2\x80\x99没有描述实际的过程。有时它\xe2\x80\x99s称为\xe2\x80\x9c内存管理\xe2\x80\x9d,这更适合,通常情况下,内存管理器也负责分配,因此也决定了堆的组织方式。

\n\n

在典型的实现中,您可以将子任务标识为

\n\n
    \n
  • 标记
    \n识别仍在使用的对象的过程(也称为跟踪)
  • \n
  • 清理
    \n清理间隙的过程,或者将它们添加到可用内存列表中或为以下过程之一做好准备:
  • \n
  • 复制
    \n将特定内存区域的活动对象重新定位到新区域,以便源区域随后完全空闲
  • \n
  • 压缩
    \n重新定位同一区域内特定内存区域的一些活动对象,填充间隙,以便该区域在开头或结尾具有连续的可用内存
  • \n
\n