这个问题是continuation of this one,但要求更具体的情况。
假设我们有以下课程:
public class Person {
private Foot left, right;
public Person(Foot left, Foot right) {
this.left = left;
this.right = right;
}
}
如果我们将其转化为以下内容,我想知道以下类是否可以从GC的角度进行优化:
public class Person {
private final Foot left, right;
public Person(Foot left, Foot right) {
this.left = left;
this.right = right;
}
}
如果我正在查看这个类,我可以立即告诉左右变量永远不能提前设置为null。这意味着,只有当父类Person的引用达到零时,GC才需要收集此类的左对象和右对象(并减少对它的引用)。它还应该意味着它可以在收集左右脚对象的同时收集人;也导致更少的运行和加速。
因此,在这个例子中,标记私有成员变量是否意味着代码甚至会导致垃圾收集中的次要加速(或者它可能用作加速点)?
答案 0 :(得分:7)
分配给字段不会触发任何垃圾收集器工作或引用计数调整,因为Java GC不使用引用计数(*)。所以答案是将字段声明为final
将对垃圾收集器性能没有影响。 (收集器的跟踪阶段必须检查字段是否为final
。
可以想象,将字段声明为final
可以帮助JIT编译器的数据流分析和内存提取的优化。但是,将其用作将字段更改为final
的理由是不明智的。如果您打算这样做,请出于正确原因(即在并发环境中使构造安全)或出于风格原因(即使代码更易于理解和维护)来执行此操作。
(*没有主流Java实现依赖于引用计数来实现内存管理。理论上可能有人可能实现使用引用计数的JVM,但传统观点认为引用计数非常低效...更不用提并发问题,收集周期等等。)
答案 1 :(得分:1)
GC优化不可能的唯一原因,是因为JVM规范 允许 更改{{ 1}}字段。
final
字段在对象构建过程中具有特殊语义,这对于构建过程在 java内存模型上正常工作非常重要。但是你可以打破规则并使用反射来改变它。在这种情况下,您不能依赖final
字段的语义(关于 java内存模型)
罢工:对不起,伙计们,我不知道我在说什么。 final 与GC无关。即使 final 根本不可更改,GC也无法获得有关该事实的任何有用信息
答案 2 :(得分:0)
Java垃圾回收不通过引用计数工作。它的工作原理是检查对象的可达性。