gpt4 book ai didi

java - JVM 何时将成员变量引用存储在堆栈上?

转载 作者:行者123 更新时间:2023-11-29 04:12:10 24 4
gpt4 key购买 nike

我正在阅读 section 12.6.1 of Java SE specs它说:

Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage. Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.

相关代码为:

class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}

我的问题是,哪种 JVM 会将 finalizerGuardian 存储在堆栈中而不是堆中,为什么?

最佳答案

代码示例用于说明引用文本的最后一句话,“请注意,仅当引用在堆栈上而不是存储在堆中时才允许进行这种优化”并且它是有点奇怪,你把它从解释文本上撕下来了:

For example, consider the Finalizer Guardian pattern:

 class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}

The finalizer guardian forces super.finalize to be called if a subclass overrides finalize and does not explicitly call super.finalize.

If these optimizations are allowed for references that are stored on the heap, then a Java compiler can detect that the finalizerGuardian field is never read, null it out, collect the object immediately, and call the finalizer early. This runs counter to the intent: the programmer probably wanted to call the Foo finalizer when the Foo instance became unreachable. This sort of transformation is therefore not legal: the inner class object should be reachable for as long as the outer class object is reachable.

所以代码示例说明了一个限制。规范中提到的“优化转换”包括在Escape Analysis证明一个对象是纯本地的之后应用的Object Scalarization,换言之,优化的代码跨越对象的整个生命周期。

但它不需要这样的本地对象。正如规范已经提到的,优化代码可以将对象的字段保留在 CPU 寄存器中,而无需重新读取它们,因此不再需要保留对象引用。同样,仍在范围内的引用变量可能未被使用。如果该引用是对某个对象的唯一引用,则将其从优化代码中移除可允许更早的垃圾回收。

这两种情况仍然允许 Foo 实例被更早地消除或收集。这反过来将允许较早的对象集合(不再)被 finalizerGuardian 引用。但这并不能抵消这种限制的意图。规范将优化限制为不允许内部对象比外部对象更早地被收集,但是将两者一起收集是没有问题的,包括比天真预期的更早。

通常,任意大的对象图可能会在单个垃圾回收周期中被回收,可能比天真预期的要早,甚至完全被优化掉。

关于java - JVM 何时将成员变量引用存储在堆栈上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54500923/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com