Re: Local variables in Java
ankur wrote:
So I was wondering how local variables are handled in Java. If the
same method is called upon many objects ( of same type) I guess the
method calls happen one after the another so that for each method call
new local variables get defined , but at any point in time there is
only one copy of all local variables defined ( while method calls are
happening). Correct ???
Jim Korman wrote:
No! Each invocation of the method gets its own "frame" containing its
own local variables.
But beware, those local variables can be pointed to shared objects.
You'll be safe if the objects are created expressly for the method and within it:
public class Foo implements Runnable
{
public void run()
{
Bar bar = new Bar();
// etc.
}
}
Since 'bar = new Bar()' happens entirely "inside" the method, the reference
'bar' will vanish at the end of the method. If the reference hasn't been
shared with anyone else, then no one references that particular Bar any more.
The creation of that new Bar is completely independent no matter how many
threads within the Foo object are doing it, no matter how many Foo instances
are doing it. Each separate variable 'bar' is, as Jim Korman explained,
within the frame of the individual method invocation and not shared, and each
'new' is brand new to that method's frame.
However:
public class Fool implements Runnable
{
private Bar myBar = new Bar();
public void run()
{
Bar bar = myBar;
// etc.
}
}
This is a different situation. Even though the *variable* 'bar' is local to
the run() method, it points to the same 'Bar' instance as the variable
'myBar', and this instance is subject to influence by all users of a single
'Fool' instance. This is especially cause for attention in multi-threaded
scenarios.
So if that single 'Fool' instance in its run() method were to affect the
object that its method-local 'bar' variable points to, it would change the
same object as the instance variable 'myBar' points to.
By an inverse of this procedure:
public void run()
{
Bar bar = new Bar();
myBar = bar;
.... }
you have what is called an "escaping" reference. What starts as a "local"
object becomes known to the whole instance, or even via a static variable to
the whole class, or to another class, or to another thread. Even when the
'bar' reference goes out of scope, the 'myBar' reference continues to make the
'Bar' object reachable. If that same reference becomes visible outside the
thread that created it, it has "escaped the thread". You get both
synchronization and garbage collection consequences.
So in order to fully answer the original question, the safety of a variable
has to do with two things, the scope of the variable (block, method, instance,
class and how those intersect with threads), and the lifetime of the object.
Sometimes they match, sometimes they don't.
You could have a local variable point for a short time to a long-lived object
while it does something useful, much as a valet possesses your car for a
little while, or the object could be created for the lifetime of the variable
and no longer, as a car for the crash-test dummy.
You as the car's owner will have to synchronize with the valet if you want to
avoid problems with deciding who gets to drive. The crash-test dummy doesn't
need to worry about sharing his car object - it only lasts for the duration of
the run() method of the CrashTest class, and it gets no other drivers.
The same CrashTest lab can run multiple tests without worry - it creates a new
dummy and a new car for each run(). The valet has to drive many cars - he's
the variable that points to many different objects with each run(). There
could be a problem if many patrons show up at the premiere too quickly and he
cannot service all those cars at once.
--
Lew