Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 526
Dinkan Avatar asked Feb 12 '16 15:02

Dinkan


People also ask

How are variables placed on the stack?

The stack is used for dynamic memory allocation, and local variables are stored at the top of the stack in a stack frame. A frame pointer is used to refer to local variables in the stack frame. Figure 110: Stack frame before and after the LINK instruction.

How local variables are stored in stack Java?

Local variables are created in the stack. Instance variables are created in the heap & are part of the object they belong to. Reference variables are created in the stack.

What does the JVM store in the stack?

A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return.

Do instance variables live on the stack?

All Local Variables and method calls gets stored in Stack , But Instance variables and Objects reside inside the Heap .


1 Answers

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:

  1. The new opcode creates a new instance of Bar and stores the reference on the stack.
  2. dup creates a copy of the same reference on the top of the stack (so you've got two copies now sitting there)
  3. invokespecial #3 calls the constructor of Bar and consumes the top of the stack. (now we've only got one copy left)
  4. 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:

  1. getstatic #6 pushes the value of System.out on the stack
  2. aload_1 pushes local variable number 1 (a) on the stack too
  3. 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.

like image 99
biziclop Avatar answered Nov 09 '22 16:11

biziclop