“this”引用是否存储在Java中的调用堆栈上?

2022-09-04 21:59:29

我们已经知道,当我们在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()
+-------------+

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

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

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

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

更新

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

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


答案 1

围绕堆栈计算机模型构建的大多数语言的工作方式与您描述的完全相同。这包括Java,.NET和C++。

可以这样想:实例方法的代码很可能在类的所有实例之间共享,如果该公共部分(methiod实现的代码,请记住,它只是计算机的内存)在所有实例中都是相同的,那么复制每个实例的数据都没有多大意义。

因此,实例方法与静态(在 Java 和 .NET 语言中)方法的区别在于添加到每个方法签名中的隐式此参数。隐式 this 参数表示方法应在其上运行的实例。由于传递给方法的参数最有可能发生在堆栈上,因此此参数将存储在堆栈上。(请参阅Java http://zeroturnaround.com/articles/java-bytecode-fundamentals-using-objects-and-calling-methods/#objects,它在.NET中是一样的)。在调用方法之前,this 参数作为第一个参数推送到堆栈上,然后是所有其他参数。

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

在示例代码中要注意的另一件事是,您使用了两次变量名称“y”,因此在方法中,局部变量“y”将隐藏实例变量,除非您用“this”对其进行了显式限定。


答案 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.