2012-04-20 61 views
12

我們已經知道,當我們在Java中調用方法時,參數和局部變量將被存儲在堆棧中。'this'引用是否存儲在Java的調用堆棧中?

例如下面的代碼:

public class Test 
{ 
    int x = 10; 
    int y = 20; 

    void test(int y) 
    { 
     int z = y; 
     this.x = y; // How JVM knows where is our current object? 
    } 

    public static void main(String [] args) 
    { 
     Test obj = new Test(); 
     obj.test(3); 
    } 
} 

會產生類似下面,我們打電話時obj.test()調用堆棧:不存儲在何處的methodthis參考我想知道

|    | 
+-------------+ 
|  z  | 
|  y  | obj.test() 
+-------------+ 
| obj  | main() 
+-------------+ 

但?它是否也存儲在堆棧中,如下所示:

|    | 
+-------------+ 
| this  | 
|  z  | 
|  y  | obj.test() 
+-------------+ 
| obj  | main() 
+-------------+ 

或者它存儲在內存中的其他區域?還是在運行時由JVM計算?

最後,我還很好奇堆棧中參數/變量obj.test()的順序是否具有特定的順序,就像C調用約定一樣,還是取決於VM的實現?

更新

我知道this是一個關鍵字,而不是一個正常的引用變量,但我的這個例子主要關注的,是如何JVM知道哪裏對象堆奠定了?或者換句話說,JVM如何知道運行時成員方法的當前對象是什麼,以便他們可以訪問這些實例變量?

+0

如果我記錯,'this'是(隱式地)作爲第一個參數的方法及其 – weidi 2012-04-20 05:47:09

+1

值得注意的是,在本機代碼和CPU的線程堆棧和在字節碼爲虛擬所描述的內容中發生的傳遞機器可以完全不同。例如如果'test()'方法被內聯,則不會有方法調用,也不會有'this'值或參數被添加到堆棧中。 – 2012-04-20 07:57:33

回答

8

大多數圍繞堆棧機模型構建的語言將與您所描述的完全相同。這包括Java,.NET和C++。

想想這樣:實例方法的代碼很可能在一個類的所有實例中共享,對於每個實例複製比數據更多的東西,如果該公共部分(無論如何,在所有實例中都是相同的。

因此,區分實例方法和靜態方法(在Java和.NET中)的方法是一個隱含的此參數,它被添加到每個方法簽名中。隱含的這個參數表示該方法應該運行的實例。由於傳遞給方法的參數很可能發生在堆棧上,因此該參數將存儲在堆棧中。 (對於Java,請參閱http://zeroturnaround.com/articles/java-bytecode-fundamentals-using-objects-and-calling-methods/#objects,在.NET中它相當類似)。在調用方法之前,該參數將作爲第一個參數推入堆棧,然後是所有其他參數。

現在,它描述了虛擬機的模型。如果JIT機器代碼確實將此參數傳遞到堆棧或寄存器中(或以任何其他方式),則該代碼完全實現特定且對VM透明。

在示例代碼中需要注意的一點是,您使用了變量名'y'兩次,因此在該方法中,局部變量'y'將影響實例變量,除非您明確地用'這個'。

+0

謝謝,這是一個非常明確的解釋。 :) – 2012-04-20 06:14:59

1

您的問題是: - JVM如何在運行時知道成員方法的當前對象,以便他們可以訪問這些實例變量。

What i know is , when u call a method with its object then implicitly 
your object reference is passed to your method. like.... 

obj.test(obj,3); 

And at run time this object is cached in this keyword.. that means this is local 
for that method and must be get m/m in stack.