0

Does jvm reuse existing reference in case it's decalred inside loop or create new one every iteration? Example:

for (SomeObject o : collectionsOfObjects){
  Date temporaryDate = o.getDate();
}

vs

   Date temporaryDate = null;
   for (SomeObject o : collectionsOfObjects){
     temporaryDate = o.getDate();
    }

Just to make sure I wonder if first example will result in more memory consumption since every loop we create new reference of type Date or maybe jvm optimize it underneath and uses same reference every iteration.

marm
  • 3
  • 1
  • How reference can be reused? – Andremoniy Feb 15 '17 at 13:42
  • It can point to different object than at beginning – marm Feb 15 '17 at 13:43
  • 3
    I think you're using the word "reference" incorrectly. Do you mean "Does the variable `temporaryDate` use the same storage location on each iteration"? (The reference is the *value* of the variable, and that will depend on the objects being iterated over.) – Jon Skeet Feb 15 '17 at 13:44
  • Possible duplicate of [Difference between declaring variables before or in loop?](http://stackoverflow.com/questions/407255/difference-between-declaring-variables-before-or-in-loop) – Saeed Feb 15 '17 at 13:46
  • http://stackoverflow.com/questions/407255/difference-between-declaring-variables-before-or-in-loop – Saeed Feb 15 '17 at 13:47
  • Post above contains discussion about primitive variable, my whole point is if jvm wastes 8 bytes of memory every iteration for new reference, I dont care about object itself. – marm Feb 15 '17 at 13:50
  • You are attempting to pre-optimize, and the optimization would be micro, two forms of optimization you should avoid. 1: Worrying about optimizing things before you know they are a problem towards resources can waste a lot of time. 2: Either way you declare it, the resource difference is negligable (8 bytes, and it's kept on the stack), so you should prefer the more readable alternative – Vince Feb 15 '17 at 14:14
  • In the first snippet, the compiler should be smart enough to allocate the reference only once and use the same memory each time through the loop (if that was what you were asking?) (and even if it didn’t, I would still clearly prefer that version). – Ole V.V. Feb 15 '17 at 14:18
  • And let's not forget that even though you created `temporaryDate`, `SomeObject o` still exists, consuming the same amount of data it does in your first example. – Vince Feb 15 '17 at 14:20
  • Ye I was just searching for confirmation that jvm is smart enough to use same reference instead of creating new ones. And if I were to code obviously I would go with smallest possible scope of variable, nevertheless I was curious how will jvm behave in that situation. – marm Feb 15 '17 at 14:23

1 Answers1

0

The scope of local variables is a compile-time artifact. This information is already lost, when the compiler (e.g. javac) produces bytecode from your source code.

Java bytecode references storage within a stack frame, equivalent to local variables, by a positional number. The assignment of local variables to these positions and the calculation of the maximum storage required in a stack frame is done at compile time.

The compiler may reuse storage within a stack frame for variables having disjunct scopes, but is not required to (it usually does). But in your example, there are no variables with disjunct scopes. Within the loop’s body, three variables exist at the same time, temporaryDate, o and an unnamed variable holding an Iterator. Since there is a point where these variable all exists at the same time, they must have different storage positions and the stack frame must have a size of at least three. This applies to both variants, hence, there is no relevant difference.

But since storage within a stack frame can only be reused for variables with disjunct scopes, limiting the scope of variables (which is a good practice anyway) can improve the reuse, e.g. when you write

for(SomeObject o : collectionsOfObjects){
  Date temporaryDate = o.getDate();
}
for(OtherObject other : collectionsOfObjects){
  String n = other.getName();
}

the storage of all three variables required for the first loop can be reused in the second loop (the different type doesn’t matter). If temporaryDate was declared outside the loop, reusing its storage in the second loop would be impossible.

Note that the stack frame is allocated at the method entry and destroyed at method exit anyway. Declarations of local variables do not cause an allocation, or any action at all. At runtime, only the actual reads and writes matter. So the way you declare the variables has no performance impact.

When the JVM starts optimizing the code (talking about a sophisticated JVM like HotSpot/OpenJDK), it converts the code into the Static single assignment form, which is likely to look entirely different to your declarations. This form enables fundamental optimization like complete removal of unused variables, folding variables predictably holding the same value into one and eliminating redundant calculations or replacing them with their predicted result.

Holger
  • 285,553
  • 42
  • 434
  • 765