垃圾回收器是否从Metaspace收集垃圾?

11

我一直认为垃圾收集器只清除堆,现在我仍然这么认为。

在Java 8中,永久代被删除,并被元空间所取代。

根据我的理解,元空间是可以进行垃圾回收的(https://dev59.com/TGAf5IYBdhLWcg3w_W5j#24075360)。

那么谁来清理元空间的垃圾呢?


我不确定我是否理解了你的意思,但我认为GC只能从Java堆中收集垃圾,而Metaspace不在Java堆内。 - gstackoverflow
1个回答

11
我认为你的困惑源于口语化的术语“垃圾回收”,尽管这个术语广泛使用,但并不真正描述在托管环境中发生的事情。 内存管理是一个复杂的过程,简单地说,它涉及以下方面:
  • 识别垃圾对象,实际上是一种确定哪些对象是可达的(即非垃圾)并将未遇到的所有内容视为垃圾的过程。
  • 将对象引用排队到引用队列和/或触发终结,如果必要。
  • 回收以前被垃圾占用的内存,这也可能相反:有时还会将活动对象移动到不同的内存空间中。
因此,对于不包含Java对象的内存空间,通常前两个点都没有多大意义,这正是你所担心的问题。解决前两个点的算法通常仅处理Java堆(定义为包含普通Java对象实例和类似结构化数据的空间)。
你提供的声明,即“Metaspace是可以进行垃圾回收的”,似乎主要涉及第三点。它是关于如果Metaspace内存不再需要,那么内存可能会被回收的事实。这并不意味着需要遍历Metaspace内活动引用或类似的内容。显然,当与其关联的`Class`和`ClassLoader`变得不可达时,类元数据已经过时,它们都是普通(几乎是)对象,存在于Java堆上。
因此,当Metaspace大小达到限制时,将触发垃圾回收,但关于前两个要点,它不会处理Metaspace,因为Metaspace不能告诉您`Class`是否已被使用。这将是一个普通的垃圾回收,但它将是“Full GC”或当前使用的GC算法具有包含类和类加载器的内存段(也称为“代”)中的垃圾回收模式的术语。
一旦收集了`Class`和`ClassLoader`堆实例,其关联的Metaspace数据也可以在清理期间被回收。

那么,将使用不同的垃圾回收器算法来收集元空间吗?(意思是它既不是小GC也不是大GC),因为收集元空间的方式与收集堆的方式不同。 - amarnath harish
1
@amarnathharish 嗯,必须有专门的代码来释放元空间中的内存,这与其他空间不同,但由于存储在元空间中的工件与类相关联,因此取决于类的收集能力来回收这些内存。而检测到类无法访问通常发生在主要GC(也称为“完全GC”)中。 - Holger
感谢您的快速回复,所以只要老年代被填满或者元空间调整发生时就会发生完全GC?当这种情况发生时,它会收集所有老年代和元空间,而不管需要收集什么? - amarnath harish
3
@amarnathharish,您可以这样看待这个问题,或者您可以考虑这样做来回收元空间内存:必须收集旧一代(以识别不可访问的类),而当由于旧一代填满而收集旧一代时,有关可回收元空间工件的信息会作为免费副产品得到。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接