Can the GV JVM move objects in the middle of a link comparison, which causes the comparison to fail even when both sides refer to the same object?

It is well known that GCs sometimes move objects in memory. And, as far as I know, as long as all links are updated when the object moves (before calling any user code), this should be absolutely safe.

However, I noticed that someone mentions that link comparisons can be unsafe because the object is moved by the GC in the middle of the comparative comparison, so that the comparison may fail even if both links must reference the same object?

those. Is there a situation in which the following code will not print "true"?

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

I tried to use this game, and the lack of reliable results makes me believe that the person who stated this was wrong, but I found many forum posts ( like this one ) that seemed to indicate that he was right . But there are also people in this thread who say that this should not be.

+56
java garbage-collection jvm
Jan 12 '16 at 8:51
source share
8 answers

Java Bytecode instructions are always atomic with respect to the GC (i.e. no loop can happen while one command is executed).

The only time the GC starts is between two Bytecode instructions.

Looking at the bytecode that javac generates for the if statement in your code, we can simply check if the GC will 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 

In addition, even if the GC was able to start during the execution of the bytecode instruction, object references would not change. This is the same object before and after the cycle.

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

+47
Jan 12 '16 at 9:22
source share

Source:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.21.3

Short answer looking at java 8 spec: None.

The == operator always checks for equality of objects (provided that no link is null). Even if the object is moved, the object remains the same object .

If you see this effect, you just discovered a JVM error. Go forward it.

Of course, it may be that some obscure JVM implementation does not apply this for some strange performance reason. If so, it would be wise to just switch from this JVM ...

+37
Jan 12 '16 at 9:15
source share

TL; DR

You should not think of such things that it is always like this, This is a dark place. Java has clearly stated its specifications, and you should not doubt it.

2.7. Representation of objects

The Java virtual machine does not provide any specific internal structure for objects.

Source: JVMS SE8.

I doubt it! If you can doubt this very basic operator, you can doubt everything else, frustration and paranoid confidence problems - this is not the place where you want to be.

What if this happens to me? Such an error should not exist. The Oracle discussion that you presented reported an error that occurred many years ago, and somehow the OP discussion decided to pop up for no reason, or without reliable documentation of such an error that existed in recent days. However, if such an error or any other occurred to you, submit it here .

To get your worries gone, Java adjusted the pointer to the pointer approach to the JVM pointer table, you can learn more about this efficiency here .

+12
Jan 12 '16 at 10:52
source share

GCs only occur at points in the program where the state is well defined, and the JVM has accurate knowledge of where everything is in the register / stack / heap, so all links can be fixed when moving the object.

those. they cannot occur between execution of arbitrary assembly instructions. Conceptually, you can think that they occur between JVM bytecode instructions when the GC configures all the links that were generated by previous instructions.

+11
Jan 12 '16 at 9:16
source share

You ask a question with the wrong premise. Since the == operator does not compare memory cells, it is not wise to change the memory location as such. The == operator, applied to links, compares the identity of the objects mentioned, regardless of how the JVM implements it.

To name an example that counteracts conventional understanding, a distributed JVM can have objects stored in RAM on different computers, including the possibility of local copies. So just comparing addresses will not work. Of course, its implementation of the JVM ensures that the semantics defined in the Java Language Specification are not changed.

If a particular JVM implementation implements link comparison by directly comparing memory locations with objects and has a garbage collector that, of course, can change memory locations, down to the JVM, to ensure that these two functions cannot interfere with each other in an incompatible way.

If you are wondering how this might work, for example. inside optimized JIT-compiled code, granularity is not as good as you might think. Each sequential code, including advanced branches, can be considered executed fast enough to delay collection of garbage until it is completed. Thus, garbage collection cannot happen at any time inside optimized code, but must be allowed at certain points, for example.

  • reverse branches (note that due to the unfolding of the loop, not every iteration of the loop implies a reverse branch)
  • memory allocation
  • thread synchronization actions
  • calling a method that has not been embedded / parsed
  • maybe something special i forgot

Thus, the JVM emits code containing certain “safe points” at which it is known, which links are currently stored, how to replace them if necessary, and, of course, changing locations does not affect the correctness. Between these points, the code can work without worrying about the possibility of changing the location of the memory, while the garbage collector will wait for the code to reach a safe point, when necessary, which is guaranteed to happen in a finite, fairly short time.

But, as said, these are implementation details. At the formal level, things like changing the location of a memory do not exist, so there is no need to explicitly indicate that they are not allowed to change the semantics of Java code. No implementation details are allowed to do this.

+5
Jan 13 '16 at 12:18
source share

I understand that you ask this question after someone says that he behaves this way, but really asks if he behaves this way, is not the right approach to assessing what they said.

What you really need to ask (first of all, you yourself, others, only if you cannot decide the answer), does it make sense for the GC to be allowed to cause the comparison to fail, which should logically be successful (basically any comparison that does not contain a weak link).

The answer to this is obviously “no,” since it could have broken almost anything except “hello world” and possibly even that.

So, if allowed, this is a mistake - either in the specification or in the implementation. Now, since the specifications and implementation were written by people, perhaps such an error exists. If so, it will be reported and almost certainly recorded.

+1
Jan 13 '16 at 7:45
source share

No, because that would be grossly ridiculous and a patent error.

GC takes great care backstage to avoid the catastrophic destruction of everything. In particular, it will only move objects when threads are paused on safepoints , which are specific places in the running code generated by the JVM for threads, has stopped. The stream in safepoint is in a known state, where the positions of all possible references to objects in registers and memory are known, so the GC can update them by pointing to the new address of the object. Garbage collection will not interfere with your comparison operations.

0
Jan 13 '16 at 20:59
source share

A Java object contains a reference to an “object” not to the memory space where the object is stored.

Java does this because it allows the JVM to manage its own memory usage (such as a garbage collector) and improve global usage without directly affecting the client program.

As an example for improvement, the first X int (I don’t remember how many) is always allocated in memory for execution for the fatser loop (ex: for (int i =0; i<10; i++) )

And as an example of an object reference, just try creating and trying to print it

 int[] i = {1,2,3}; System.out.println(i); 

You will see that Java returns something starting with [I@ . He says that it is a point in the "array at int", and then a reference to the object. Not in the memory zone!

-9
Jan 12 '16 at 9:14
source share



All Articles