我们已经知道,当我们在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如何知道成员方法在运行时的当前对象是什么,因此他们可以访问这些实例变量?
答案 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.