2012-04-20 45 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.