Java的虚拟机内存分为三个区域:栈stack、堆heap、方法区method area
栈的特点:
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- JVM会为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 栈属于线程私有,不能实现线程间的共享
- 栈的存储特性是“先进后出,后进先出”
- 栈是由系统自动分配,速度快。
- 栈是一个连续的内存空间。
堆的特点:
- 堆用于存储创建好的对象和数组(数组也是对象)
- JVM只是一个堆,被所有线程共享
- 堆是一个不连续的内存空间,分配灵活,速度慢
方法区(又叫静态区)特点:
- JVM只有一个方法区,被所有线程共享
- 方法区实际也是堆,只是用于存储类、常量相关的信息
- 用来存放程序中永远是不变或唯一的内容(类信息[Class对象]、静态变量、字符串常量等)
public class HKStu {
int id;
String sname;
int age;
Computer comp;
void study(){
System.out.println("使用电脑学习"+comp.brand);
}
void play(){
System.out.println("我在玩游戏");
}
HKStu(){
//构造方法。用于创建这个类的对象。无参的构造方法可以由系统自动创建。
}
public static void main(String[] args) {
HKStu student = new HKStu();
student.id = 7036;
student.sname = "Java";
student.age = 25;
Computer compt = new Computer();
compt.brand = "MacBook";
student.comp = compt;
student.study();
student.play();
}
}
class Computer{
String brand;
}
以上述代码为例,编译后,首先从PSVM开始,程序分配栈、堆和方法区。
- 代码加载到方法区中,类的相关信息:代码、静态变量、静态方法、字符串常量(“使用电脑学习”、“我在玩游戏”、“Java”、“MacBook”)
- 进入main方法后,在栈中开辟main方法的空间。创建student对象,使用new方法,栈内再开辟构造方法的空间,在堆中创建对象,包括对象的属性和方法。创建完毕后,构造方法释放。
- 设置属性根据数据类型寻找赋值,如数字常量直接赋值,字符串常量去方法区中存储的字符串常量中寻找赋值
- 若中间插有其他类的属性(如Computer),创建Computer对象,在栈中为Computer的构造方法分配内存空间,在栈中创建comp对象及属性、方法,创建完后栈中构造方法的内存释放。
- student根据comp的地址寻找自己需要的属性,然后赋值
- 调用方法同理
- 全部执行完后,全部释放内存,虚拟机关闭。
如下图所示