前言
以前,学习java的时候,知道生活中的事物都可以定义为java里面的类,比如:学生汽车,食物等。而事物的性质就是java里面的属性,比如:学生的姓名,性别,年龄;汽车的品牌,价格等;食物的价格,口味等。事物的功能就是java里面的方法,例如:学生上课,考试;汽车行驶;食物烹饪等等。
但是,对于代码运行时计算机内存是如何分配和变化的这个并不了解。今天简单梳理下,Java自定义类的内存图是如何变化的。
代码
//Phone.java
public class Phone{
String color;
String brand;
double size;
}
//TestPhone.java
public class TestPhone{
public static void main(){
Phone p =new Phone();
p.color = "red";
p.brand = "iphone";
p.size = 5.0;
System.out.println(p.color+" "+p.brand+" "+p.size);
}
}
内存图变化
首先
程序经过编译后,内存图如下:(此时还没有运行)
此时的方法区里面有两个java文件编译后的.class文件,有main方法,有color,brand,size属性。
开始运行程序
- 程序开始运行后,会调用main方法,在栈内存中开辟一块内存空间,给main方法使用。
- 内存开辟好了后,JVM就会从方法区中复制一份main方法到栈内存中执行(即所谓的压栈执行,栈是运行方法用的,堆是存储容器用的),此时内存图如下:
- 按顺序执行main方法,先建立变量p
new操作的内存图变化
当我们进行new Phone时,内存出现哪些内容?
1. JVM在堆内存中开辟空间,存储对象Phone,并有了内存地址。例如为ox01.内存图如下:
2. 类中的属性,会跟随对象Phone进入堆内存,则堆内存中的对象有了属性。
3. 属性进入堆内存后就会赋予它们默认值。内存图如下:
4. JVM才会将堆内存地址ox01传给p,则p指向内存空间ox01这块区域。此时代码Phone p = new Phone();执行完了。
变量赋值操作的内存变化
- 首先,main方法里面的变量赋值语句在栈内存中,内存图如下:
- 此时,p指向的是ox01这个内存块,所以p.color,p.brand,p.size的赋值操作实际改变的是内存地址为ox01这个内存中对应属性的值,内存图如下:
- 执行输出语句,打印的也就是内存地址为ox01里面属性的值,即:”red”,”iphone”,5.0
注意
- 属性赋完默认值后,JVM就会把内存地址传递给引用类型p,变量p保存的是内存中的地址,所以P.属性无论进行什么操作,操作的都是堆内存中的变量
- main方法执行完后,p的指向就断开了,则堆内存中的对象,属性就变成垃圾,需要进行清理,内存回收。