Java程序执行过程之内存分析

基于下面的简单代码对其执行的内存进行一步步的分析,以更好的了解程序运行机制;代码如下:

public class Person {
    String name;
    int age;
    public void show(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}
public class TestPerson {
    public static void main(String[] args) {
        //创建p1对象
        Person p1 = new Person();
        p1.age = 24;
        p1.name = "张三";
        p1.show();
        //创建p2对象
        Person p2 = new Person();
        p2.age = 34;
        p2.name = "李四";
        p2.show();
    }
}

以上代码的执行结果如下:

接下来对上述代码基于内存的执行过程进行分析:

(0)首先我们将JVM的内存区域标注出来,如下图所示:

(1)以上Java代码的入口为TestPerson类中的main()方法,所以形成main方法的栈帧,如下图所示:

(2)执行代码:Person p1 = new Person();同时在方法区加载Person类信息,首先创建一个引用对象,占4个字节,然后执行构造方法创建开启一个Person的栈帧【图中未命名的栈帧为Person构造方法的栈帧】。如下图所示:

(3)同时在堆中创建一个Person对象,假设该对象的地址为:0x11,当对象创建完成后,Person构造方法的栈帧完成,将p1对象的地址0x11赋给main的p1,同时构造方法的栈帧出栈。最后结果如下图所示

(4)执行下一步,p1.age = 24;  p1.name = "张三";24为基本数据类型,所以直接在对象0x11中直接赋值,而String类型的“张三”不是基本数据类型,所以在方法区创建“张三”对象,同时将“张三”对象的地址赋给name。执行后的结果如下图所示:

(5)接下来执行p1.show();首先在栈中创建p1.show()的栈帧,同时传递隐式参数this,this指当前对象。如下图所示:

在show方法中执行打印操作,打印结果为:姓名:张三,年龄:24;

打印结束后,p1.show()方法执行完毕。p1.show()出栈。如下图所示:

(6)执行代码:Person p2 = new Person();,首先创建一个引用对象,占4个字节,然后执行构造方法创建开启一个Person的栈帧【图中未命名的栈帧为Person构造方法的栈帧】。如下图所示:

(7)同时在堆中创建一个Person对象,假设该对象的地址为:0x12,当对象创建完成后,Person构造方法的栈帧完成,将p2对象的地址0x12赋给main的p2,同时构造方法的栈帧出栈。最后结果如下图所示:

(8)执行下一步,p2.age = 34;  p1.name = "李四";34为基本数据类型,所以直接在对象0x12中直接赋值,而String类型的“李四”不是基本数据类型,所以在方法区创建“李四”对象,同时将“李四”对象的地址赋给name。执行后的结果如下图所示:

(9)接下来执行p2.show();首先在栈中创建p2.show()的栈帧,同时传递隐式参数this,this指当前对象。如下图所示:

在show方法中执行打印操作,打印结果为:姓名:李四,年龄:34;

打印结束后,p2.show()方法执行完毕。p2.show()出栈。如下图所示:

(10)同时:main()方法执行完成,main()方法出栈。如下图所示

(11)最后,堆内存中的对象和方法区的信息也没有调用,被回收。最终如下图所示:

posted @ 2020-08-08 16:36  夜月光雾  阅读(17)  评论(0编辑  收藏  举报