Related question: Scala closures compared to Java innerclasses -> final VS var
I wonder when do Scala makes the variables captured into a closure live on the heap
I don't know the insides of the compiler, but here is how it can be done. For each local variable, the compiler maintains a flag initialized to false. Whenever the variable is used, the compiler checks whether it is being used inside a class or closure that doesn't contain the variable's declaration; if so the flag is set to true. At the end of the variable's scope, if the flag is still false, the variable can live on the stack. Otherwise it must live on the heap.
An anonymous function (and actually, any function) in scala is actually an object (an instance of Function*
). When it is instantiated, the capture of vals is done by copying the vals into internal fields of the function object. In the function body (that is, in the function object's apply
method) the access to the captured vals is done by accessing these fields.
The capture of vars is similar, except that the compiler has to add a level of indirection: the var value is accessed through some hidden mutable holder (simply an object with a mutable field pointing to the current value of the var) and this is this holder that is copied into the function object. When writing into the var (either by local code or by the function object), it is the holder's field which is written. This mechanism ensures that the local code and function's code manipulate the same data, and both see each other's modifications.
So the answer is that a captured vals and a captured var both always live on the heap (whether directly as a field of the function object, or as a field of some wrapper object)