一尘不染

JVM GC是否可以在引用比较的中间移动对象,即使双方都引用同一个对象,也导致比较失败?

java

众所周知,GC有时会在内存中移动对象。据我了解,只要在移动对象时所有引用都被更新(在调用任何用户代码之前),这应该是绝对安全的。

但是,我看到有人提到引用比较可能是不安全的,因为对象在引用比较的中间被GC移动了,从而即使两个引用都应引用同一对象,该比较也可能失败?

也就是说,在任何情况下以下代码都不会显示“ true”吗?

Foo foo = new Foo();
Foo bar = foo;
if(foo == bar) {
    System.out.println("true");
}

我尝试使用谷歌搜索,但是缺乏可靠的结果使我相信说这是错误的人,但是我确实找到了各种各样的论坛帖子(例如这样的帖子),似乎表明他是正确的。但是,有人也说那不是事实。


阅读 195

收藏
2020-12-03

共1个答案

一尘不染

Java字节码指令相对于GC始终是原子的(即,执行单个指令时不会发生周期)。

GC只能运行在两个字节码指令之间。

查看javac为代码中的if指令生成的字节码,我们可以简单地检查一下GC是否会产生作用:

// a GC here wouldn't change anything
ALOAD 1
// a GC cycle here would update all references accordingly, even the one on the stack
ALOAD 2
// same here. A GC cycle will update all references to the object on the stack
IF_ACMPNE L3
// this is the comparison of the two references. no cycle can happen while this comparison
// "is running" so there won't be any problems with this either

另外,即使GC能够在执行字节码指令期间运行,该对象的引用也不会更改。在循环之前和之后,它仍然是同一对象。

因此,简而言之,您的问题的答案是“否”,它将始终输出true。

2020-12-03