jvm内存分布问题

public class Test{
    public Item item;
    
    Test(Item item){
        this.item = item;
    }
    
    public void test(){
        Item itemLocal = new Item();
    }
}

实例应该都放在堆里面
itemLocal 好像放在栈帧里面
item呢

另外两个Test对象 是不是共享代码区里面的代码方法啊

该找的 他写的对不对
clipboard.png

阅读 2.9k
3 个回答

我说一下,我的理解。

Test的例子

其实Text例子是没有给出Main方法的,也就是没有程序入口,可以说成是根本没有执行,就是Java文件存在硬盘上而已。所以其实没什么好聊的。

Person的例子

这个例子就值得分析一下,理解一个程序的时候,最好是,也是必须是先知道代码的执行顺序,才能准确的把握程序的在内存的情况。

首先,简单的说,程序执行的时候,分为三个区域,栈,堆,方法区。

当java虚拟机看到Person的时候,先把Person.class文件加载到方法区,等待使用,紧接着main方法入栈(方法存储在栈里面),

int t=10;

这个变量都属于局部变量,随着栈帧(Main方法)入栈。

String name =“xiaoming”

xiaoming的值会被存在了方法区的常量池,作为常量,等待使用,name作为句柄同样存在了栈里面。常量池里面xiaoming的存储地址赋给了句柄name。

Person xiaoMing =new Person();

在内存的情况是,xiaoMing作为对象的引用,也叫句柄,作为局部变量的一种,保存在栈里面,new出来的任何对象,都会在堆里面开辟一块空间用于存放数据。所以mAge 和 mName 是存放在开辟出来的空间俩面的,也就是堆里面。然后会生成一个内存地址,赋值给句柄,让句柄能根据赋给的地址找到数据。

但AGE_MAX 这个final static常量是特殊的,它因为是静态和最终的,会放在方法区person.class的共享区,因为他不可被更改并且要提供给所有需要它的对象使用。

随后setAge方法入栈,执行完毕,弹栈。
setName方法入栈,执行完毕,弹栈。
同理,print方法也是一样。

所以我认为是大体上他的判断是准确的。但是代码也有不规范的地方。比如说,既然有构造方法了,为什么不用构造方法进行初始化工作,使用this关键字。这样做跟专业一点,虽然他的代码也没什么错,当然这是另一个话题了。

public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

欢迎各位童鞋,批评指正。

从语法上说,itemLocal变量本身(引用)在栈里,但引用的对象在堆里;但由于JVM优化的关系,itemLocal这个变量根本就没用到,所以栈里可能不会有这个变量。

另外一个类无论实例化了几个对象,只要在同一个ClassLoader中,方法代码(bytecode)总是一个。

下面你找的例子,基本正确。

引用在栈帧中,栈帧引用的内容存在堆中

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题