Q:

How JVM know the location a variable in stack of a method?

This question may be a silly one or may be a duplicate. I am confused with how the variables are retrieved from stack when program is referring to that variable. 
An object is stored in  heap and the location is stored in the reference variable and the reference variable containing the heap address itself is stored in stack. But how JVM figure out that reference variable is stored in what location in stack. 
Lets consider the example just to make clear what I am confused about.
Class Test {
    public void test() {
        Object a = new Bar();
        Object b = new Foo();
        System.out.println(a);
    }
}

Lets say method test() is getting executed. So stack will be allocated for test().
Now when the line 'Object a = new Bar();' is executed , Bar object will be created in Heap and the actual variable 'a', whose value is the address location of the Bar object , will be stored in stack of test().
Again on the line 'Object b = new Foo();' same thing happens. Foo object will be created in Heap and the actual variable 'b' ,whose value is the address location of the Foo object,  will be stored in stack of test().
Now when he line 'System.out.println(a);' is executed , how does JVM know from which location in the stack , the value of 'a' should be retrieved. Means what links the variable 'a' and its location in the stack ?

A:

You're almost there, there's just one missing link in your understanding.
Local variables (or the references to the object stored in a local variable, if we're talking about non-primitive types) are actually stored in a local variable table, not on the operand stack. They're only pushed onto the stack when they are to be used by a call.
(What is confusing is that the local variable table itself is also stored on a stack, but that's a separate stack from what the bytecode uses for operands. From the bytecode's perspective it is a real table, with fixed size and freely indexable.)
You can use javap to look at what bytecode is generated from your code. What you'll see is something like this:
public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
  stack=3, locals=3, args_size=1
    0: new           #2                  // class Test$Bar
    3: dup
    4: invokespecial #3                  // Method Test$Bar."<init>":()V
    7: astore_1
    8: new           #4                  // class Test$Foo
   11: dup
   12: invokespecial #5                  // Method Test$Foo."<init>":()V
   15: astore_2
   16: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
   19: aload_1
   20: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   23: return
}

First of all, what is this line?
  stack=3, locals=3, args_size=1

It is metadata that tells the JVM that this method has an operand stack no deeper than 3 entries, 3 local variables and takes 1 argument. But surely that isn't right, our method takes no argument and clearly only has 2 local variables!
The answer to this is that non-static methods always have a "0th argument": this. This explains the argument count, and leads us to the next important discovery: arguments of a method are stored in the local variable table too. So our table will have entries 0,1,2, with 0 containing this at the start and 1 and 2 uninitialised.
With that out of the way, let's look at the code! First up it's lines 0-7:

The new opcode creates a new instance of Bar and stores the reference on the stack.
dup creates a copy of the same reference on the top of the stack (so you've got two copies now sitting there)
invokespecial #3 calls the constructor of Bar and consumes the top of the stack. (now we've only got one copy left)
astore_1 stores the remaining reference in local variable number number 1 (0 is for this in this case)

This is what Object a = new Bar(); has been compiled into. Then you get the same for Object b = new Foo(); (lines 8-15).
And then comes the interesting bit, from line 16:

getstatic #6 pushes the value of System.out on the stack
aload_1 pushes local variable number 1 (a) on the stack too
invokevirtual #7 consumes both entries, calling println() on System.out with a as its input parameter.

If you want to delve into it deeper, or you just want to point out my mistakes, the official reference for all of the above is here.

