首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java内存模型中的实例变量

Java内存模型中的实例变量
EN

Stack Overflow用户
提问于 2013-11-15 00:17:18
回答 2查看 473关注 0票数 3

在网上搜索后,我还没有找到一个很好的全面的答案,关于实例变量在Java内存模型中的确切位置。例如,我们有这样的代码(带有变量的隐藏声明):

代码语言:javascript
复制
class A {
    int var = 1;
    void m() {
        System.out.println("\'m()\' is called from class A");
    }
}

class B extends A {
    int var = 5;
    void m() {
        System.out.println("\'m()\' is called from class B");
    }
}

public class Class1 {
    public static void main(String args[]) {
        A aref = new B();
        aref.m();
        String s = (aref.var)==1?"A":"B";
        System.out.println("\'var\' is called from class " + s);
    }
}

此代码的输出为:

代码语言:javascript
复制
'm()' is called from class B
'var' is called from class A

现在的问题不是继承在Java中是如何工作的,而是这个实例变量在Java内存模型中的位置?请对你的答案进行论证。

谢谢

EN

回答 2

Stack Overflow用户

发布于 2013-11-15 00:47:31

对象保留在堆中,但作为一个内存块,其大小等于所有变量的总和+一些额外的字节,用于存储虚拟方法表(VMT)和对象的原型位置(根据JVM实现可能更多)。

因此,您的示例对象在(32位)内存中将如下所示(指针值仅用于表示):

代码语言:javascript
复制
[0000] 0154  // pointer to prototype
[0004] 3625  // pointer to virtual method table
[0008] 0001  // int var

现在,在上面的示例中,没有成员被访问,所以JVM所做的就是定位原型的VMT,跳转到写在那里的函数地址并执行它。

如果您的var = 1代码真的通过了优化器,那么生成的汇编代码就不会知道这个"var“的事情,而是直接使用内存访问。如下所示:

代码语言:javascript
复制
set [4924 + 8], 1 

其中4924是实例的内存位置,+8是变量var的偏移量。请记住,这是(使人类可读的)程序集,而不是字节码,所以基本上,一旦JIT处理完它,剩下的就是它。

由于两个对象的大小相同,甚至可以“向上转换”A到B,唯一不起作用的原因是Java禁止这种不安全的操作。在其他不太安全的语言中,如C++,您可以很容易地做到这一点,并可能逃脱惩罚。

票数 4
EN

Stack Overflow用户

发布于 2013-11-15 00:23:23

继承时,变量与方法不同。当您的方法m()扩展A时,它会在B类中被覆盖。但是,B不能覆盖其父类的局部变量,因为它对它们没有任何权限。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19982741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档