如果保证在收集时调用 finalize() ,年轻代是否仍然具有速度优势?
Is young generation still gets speed advantage if finalize() is guaranteed to be called when collecting?
为什么年轻代的垃圾收集速度快取决于一个事实:年轻代的大多数对象很快就会死亡。所以当年轻代收集发生时,很少有还活着的对象被移动到老年代,从那时起,年轻代中的所有数据都可以被认为是无用的(部分或它们被移动,重置不可达),这无需进一步扫描即可重新使用内存的和平。在这种情况下,不会扫描无法访问的对象,从而节省大量时间。
但是我有一个问题,在 Java 中有一个方法 finalize()
(虽然它在 JAVA 9 中被弃用),如果收集器保证 finalize()
将被调用时,它需要扫描无法到达的对象,而不仅仅是遍历活体对象,速度优势似乎消失了。
所以,
- 我说的对吗? (
finalize()
使得新生代收集
速度变慢,速度优势消失。)
- 如果不是,JVM 是如何处理这个问题的? (例如,忽略
finalize()
?)
- young generation除了上面的问题还有其他的吗
优势?
编辑:
我正在为具有 finalize()
功能的语言编写 gc,在这种情况下我无法快速收集。
基本上,你做对了。但是幸存者对象不会立即复制到老年代。相反,它们被复制到 Survivor space,在它们被提升到老年代之前,它们必须在可配置数量的垃圾收集中存活下来。
但基本假设是正确的。当对象存活时间超过必要时间并且必须调用 finalize()
延长对象的生命周期时,效率会降低。
根本的解决方法是将此作为例外情况。这甚至在 the specification:
中得到解决
For efficiency, an implementation may keep track of classes that do not override the finalize method of class Object, or override it in a trivial way.
For example:
protected void finalize() throws Throwable {
super.finalize();
}
We encourage implementations to treat such objects as having a finalizer that is not overridden, and to finalize them more efficiently, as described in §12.6.1.
在 HotSpot JVM 的情况下,它会识别何时由 Object
继承的方法未被覆盖或何时被空方法覆盖。 Afaik,单独的 super 调用并不总是被识别,但对于您自己的语言,它可能会被识别。
所以对于Java中的大部分对象来说,finalize()
不需要调用,因为它无论如何都没有效果,也永远不会被调用。这解决了延长生命周期的问题,因为它现在只适用于少数对象。
通过拥有一个特殊的引用对象来消除扫描死对象的需要,该引用对象仅为那些具有非平凡的终结器的对象创建,它本身保持可达。所以它仍然只是必须扫描的可达对象。可以在 .
中找到更多详细信息
为什么年轻代的垃圾收集速度快取决于一个事实:年轻代的大多数对象很快就会死亡。所以当年轻代收集发生时,很少有还活着的对象被移动到老年代,从那时起,年轻代中的所有数据都可以被认为是无用的(部分或它们被移动,重置不可达),这无需进一步扫描即可重新使用内存的和平。在这种情况下,不会扫描无法访问的对象,从而节省大量时间。
但是我有一个问题,在 Java 中有一个方法 finalize()
(虽然它在 JAVA 9 中被弃用),如果收集器保证 finalize()
将被调用时,它需要扫描无法到达的对象,而不仅仅是遍历活体对象,速度优势似乎消失了。
所以,
- 我说的对吗? (
finalize()
使得新生代收集 速度变慢,速度优势消失。) - 如果不是,JVM 是如何处理这个问题的? (例如,忽略
finalize()
?) - young generation除了上面的问题还有其他的吗 优势?
编辑:
我正在为具有 finalize()
功能的语言编写 gc,在这种情况下我无法快速收集。
基本上,你做对了。但是幸存者对象不会立即复制到老年代。相反,它们被复制到 Survivor space,在它们被提升到老年代之前,它们必须在可配置数量的垃圾收集中存活下来。
但基本假设是正确的。当对象存活时间超过必要时间并且必须调用 finalize()
延长对象的生命周期时,效率会降低。
根本的解决方法是将此作为例外情况。这甚至在 the specification:
中得到解决For efficiency, an implementation may keep track of classes that do not override the finalize method of class Object, or override it in a trivial way.
For example:
protected void finalize() throws Throwable { super.finalize(); }
We encourage implementations to treat such objects as having a finalizer that is not overridden, and to finalize them more efficiently, as described in §12.6.1.
在 HotSpot JVM 的情况下,它会识别何时由 Object
继承的方法未被覆盖或何时被空方法覆盖。 Afaik,单独的 super 调用并不总是被识别,但对于您自己的语言,它可能会被识别。
所以对于Java中的大部分对象来说,finalize()
不需要调用,因为它无论如何都没有效果,也永远不会被调用。这解决了延长生命周期的问题,因为它现在只适用于少数对象。
通过拥有一个特殊的引用对象来消除扫描死对象的需要,该引用对象仅为那些具有非平凡的终结器的对象创建,它本身保持可达。所以它仍然只是必须扫描的可达对象。可以在