Bri*_*Hsu 13 java callstack this 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);
}
}
Run Code Online (Sandbox Code Playgroud)
当我们调用时,会产生如下所示的调用堆栈obj.test():
| |
+-------------+
| z |
| y | obj.test()
+-------------+
| obj | main()
+-------------+
Run Code Online (Sandbox Code Playgroud)
但我想知道存储this在哪里引用method?它是否也存储在堆栈中,如下所示:
| |
+-------------+
| this |
| z |
| y | obj.test()
+-------------+
| obj | main()
+-------------+
Run Code Online (Sandbox Code Playgroud)
或者它存储在内存中的其他区域?或者它是在运行时由JVM计算的?
最后,我也很好奇obj.test()堆栈中的参数/变量的顺序是否有特定的顺序,就像C有调用约定,或者它取决于VM的实现?
更新:
我知道this是一个关键字而不是一个普通的引用变量,但我对这个例子的主要关注点是JVM如何知道对象在堆中的位置?
或者换句话说,JVM如何在运行时知道成员方法的当前对象是什么,因此他们可以访问这些实例变量?
围绕stackmachine模型构建的大多数语言都会像您描述的那样工作.这包括Java,.NET和C++.
以这种方式思考:实例方法的代码最有可能在一个类的所有实例中共享,除了每个实例的数据之外,复制任何东西都没有多大意义,如果那个公共部分(用于实现方法的代码)无论如何,记住它对计算机的所有内存都是相同的.
因此,将实例方法与静态(在Java和.NET中说)方法区别开来的是一个隐含的this参数,它被添加到每个方法签名中.隐含的this参数表示该方法应该操作的实例.因为传递给方法的参数很可能发生在堆栈上,所以这个参数将存储在堆栈中.(请参阅http://zeroturnaround.com/articles/java-bytecode-fundamentals-using-objects-and-calling-methods/#objects for Java,它在.NET中的表现非常相似).在调用方法之前,将此参数作为第一个参数压入堆栈,然后是所有其他参数.
现在,它描述了虚拟机的模型.如果JITed机器代码真的通过堆栈或寄存器(或以任何其他方式)传递此参数,则完全是特定于实现的并且对VM是透明的.
在示例代码中要注意的另一件事是你使用变量名'y'两次,因此在方法中,局部变量'y'将影响实例变量,除非你明确地用'this'限定它.
| 归档时间: |
|
| 查看次数: |
1094 次 |
| 最近记录: |