众所周知,GC有时会在内存中移动对象。据我了解,只要在移动对象时所有引用都被更新(在调用任何用户代码之前),这应该是绝对安全的。
但是,我看到有人提到引用比较可能是不安全的,因为对象在引用比较的中间被GC移动了,从而即使两个引用都应引用同一对象,该比较也可能失败?
也就是说,在任何情况下以下代码都不会显示“ true”吗?
Foo foo = new Foo(); Foo bar = foo; if(foo == bar) { System.out.println("true"); }
我尝试使用谷歌搜索,但是缺乏可靠的结果使我相信说这是错误的人,但是我确实找到了各种各样的论坛帖子(例如这样的帖子),似乎表明他是正确的。但是,有人也说那不是事实。
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。