java: If I assign a variable the same value as just before, does it change the memory or does JIT recognize this?

Viewed 111

For example:

class Main {
   public boolean hasBeenUpdated = false;

   public void updateMain(){
     this.hasBeenUpdated = true;
     /*
     alternative:
     if(!hasBeenUpdated){
       this.hasBeenUpdated = true;
     }
     */
   }

   public void persistUpdate(){
     this.hasBeenUpdated = false;
   }
}

public Main instance = new Main()
instance.updateMain()
instance.updateMain()
instance.updateMain()

Does instance.hasBeenUpdated get updated 3 times in memory?

The reason I ask this is because I hoped to use a boolean("hasBeenUpdated") as a flag, and this could theoretically be "changed" many, many times, before I call "instance.persistUpdate()".

Does the JVM's JIT see this and perform an optimization?

3 Answers

JIT will collapse redundant statements only when it can PROVE that removing the code will not change the behavior. For example, if you did this:

int i;
i = 1;
i = 1;
i = 1;

The first two assignments are provably redundant, and the JIT could eliminate them. If instead it's

int i;
i = someMethodReturningInt();
i = someMethodReturningInt();
i = someMethodReturningInt();

the JIT has no way of knowing what someMethodReturnintInt() does, including whether it has any side effects, so it must invoke the method 3 times. Whether or not it actually stores any but the final value is immaterial, as the code would behave the same either way. (Declaring volatile int i; instead would force it to store each value)

Of course if you're doing other things in between the method invocations the it will be forced to perform the assignment.

The whole topic is part of the more general "happens-before" and "happens-after" concepts documented in the language and JVM specifications.

Optimization is NEVER supposed to change the behavior of a program, except possibly to reduce its runtime. There have been instances where bugs in the optimizer inadvertently did introduce errors, but these have been few and far between. In general you don't need to worry about whether optimization will break your code.

It can perform an optimization, yes.

As a matter of fact, it can issue a single write, or a single call to updateMain. All those three calls will be collapsed to one, only.

But for that to happen, JIT has to prove that nothing else breaks, or more specifically that code does not break the JMM rules. In this specific case, as far as I understand it, it does not.

Given the choice is between JVM code that implements

   move new value to variable

and

   compare new value with current value of variable
   if not the same
       move new value to variable

the JVM would have to be fairly nutty to implement it the latter way. That's a pessimization, not an optimization.

The JVM to a large extent relies on the real machine to do simple operations, and real machines store values in memory when you tell them to store values in memory.

Related