这是'这个'存储在Java中的调用堆栈上的引用?

时间:2012-04-20 05:26:46

标签: java this callstack calling-convention

我们已经知道,当我们在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()时会生成如下所示的调用堆栈:

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

但我想知道存储在this中的method引用在哪里?它是否也存储在堆栈中,如下所示:

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

或者它存储在内存中的其他区域?或者它是在运行时由JVM计算的?

最后,我也很好奇堆栈中obj.test()的参数/变量的顺序是否具有特定的顺序,就像C具有调用约定,或者它取决于VM的实现? / p>

更新

我知道this是关键字而不是普通的引用变量,但我对这个例子的主要关注点是JVM如何知道对象在堆中的位置?

或者换句话说,JVM如何知道成员方法在运行时的当前对象是什么,因此他们可以访问这些实例变量?

2 个答案:

答案 0 :(得分:9)

围绕stackmachine模型构建的大多数语言都可以像您描述的那样工作。这包括Java,.NET和C ++。

以这种方式思考:实例方法的代码很可能在一个类的所有实例中共享,复制除了每个实例的数据之外的任何东西都没有多大意义,如果那个公共部分(代码)无论如何,对于methiod实现,记住它对计算机的所有内存都是相同的。

因此,将实例方法与静态(在Java和.NET中说)方法区别开来的是一个隐含的this参数,它被添加到每个方法签名中。隐含的this参数表示该方法应该操作的实例。因为传递给方法的参数很可能发生在堆栈上,所以这个参数将存储在堆栈中。 (请参阅http://zeroturnaround.com/articles/java-bytecode-fundamentals-using-objects-and-calling-methods/#objects了解Java,它与.NET中的相同之处)。在调用方法之前,将此参数作为第一个参数压入堆栈,然后是所有其他参数。

现在,它描述了虚拟机的模型。如果JITed机器代码真的通过堆栈或寄存器(或以任何其他方式)传递此参数,则完全是特定于实现的并且对VM是透明的。

在你的示例代码中要注意的另一件事是你使用变量名'y'两次,因此在方法中,局部变量'y'将影响实例变量,除非你明确地用'this'限定它”。

答案 1 :(得分:2)

您的问题是: - 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.