JVM GC是否可以在参考比较中移动对象,导致比较失败,即使双方都指向相同的对象? [英] Can the JVM GC move objects in the middle of a reference comparison, causing a comparison to fail even when both sides refer to the same object?

查看:131
本文介绍了JVM GC是否可以在参考比较中移动对象,导致比较失败,即使双方都指向相同的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



即,有没有什么情况下下面的代码不会显示true?

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

我试着用google搜索,缺乏可靠的结果让我相信声称这是错误的人,但我确实找到了各种各样的论坛帖子(像这个),似乎表明他是正确的。但是该线程也有人说它不应该是这种情况。

解码方案

Java字节码指令始终是原子的GC(即执行单个指令时不会发生循环)。



GC运行的唯一时间是两条Bytecode指令。



查看javac生成的字节码对于代码中的if指令,我们可以简单地检查一下GC是否会产生任何影响:

  // a GC here不会改变任何东西
ALOAD 1
//一个GC循环会相应地更新所有的引用,即使是堆栈中的引用
ALOAD 2
//这里也是一样的。 GC周期将更新堆栈中对象的所有引用
IF_ACMPNE L3
//这是两个引用的比较。在比较
//正在运行时不会发生任何循环,所以不会有任何问题,或者

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



所以,简而言之,你的问题的答案是否定的,它总是会输出真实的。


It's well known that GCs will sometimes move objects around in memory. And it's to my understanding that as long as all references are updated when the object is moved (before any user code is called), this should be perfectly safe.

However, I saw someone mention that reference comparison could be unsafe due to the object being moved by the GC in the middle of a reference comparison such that the comparison could fail even when both references should be referring to the same object?

ie, is there any situation under which the following code would not print "true"?

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

I tried googling this and the lack of reliable results leads me to believe that the person who stated this was wrong, but I did find an assortment of forum posts (like this one) that seemed to indicate that he was correct. But that thread also has people saying that it shouldn't be the case.

解决方案

Java Bytecode instructions are always atomic in relation to the GC (i.e. no cycle can happen while a single instruction is being executed).

The only time the GC will run is between two Bytecode instructions.

Looking at the bytecode that javac generates for the if instruction in your code we can simply check to see if a GC would have any effect:

// 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

Aditionally, even if the GC were able to run during the execution of a bytecode instruction, the references of the object would not change. It's still the same object before and after the cycle.

So, in short the answer to your question is no, it will always output true.

这篇关于JVM GC是否可以在参考比较中移动对象,导致比较失败,即使双方都指向相同的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆