栈
#栈描述的是方法执行的内存模式,每个方法被调用时都会创建一个栈帧(存储局部变量、操作数、方法出口等)
#JVM每个线程都会创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
#栈是线程私有的,不能在线程之间实现共享
#栈的存储特性:先进后出
#栈是由系统自动分配,速度快,栈是一个连续的内存空间
#方法的运行一定在栈中运行
存放的是局部变量(注:形参也是局部变量的一种)和对象的引用声明
堆
#堆是用来存储创建好的对象和数组(数组也是对象)
#JVM只有一个堆,可以被线程共享
#堆是一个不连续的内存空间,分配灵活,速度慢
存放的是使用new关键字创建的类或者数组的(含成员变量)
注:
成员变量:在类中方法外面。由垃圾回收器负责回收
生命周期:随着对象创建而存在,随着对象销毁而消失
在内存的位置:在堆中
局部变量:在方法或者代码块中,或者方法的声明上
生命周期:随着方法的调用或者代码块的执行而存在,随着方法或者代码块执行完毕而消失
在内存的位置:在栈中
方法区(又叫静态区)
#JVM只有一个方法区,所以被线程共享
#方法区其实也是堆,只是用来存储类、常量的相关信息
#用来存放程序中永远不变的或者唯一的内容(类信息、class对象,静态变量,字符串常量等)
简单JVM内存模型图
在JVM中的栈,堆,方法区的数据交互
1.代码举例:
//运行时, jvm 把MainTest 的信息都放入方法区
public class MainTest {
//main方法本身放入方法区
public static void main(String[] args) {
Student student1= new Student("学生1");
student1.printName();
}
}
public class Student{
private String name;
//new Student() 实例后,引用放入栈, 对象放入堆
public Student(String name){
this.name = name;
}
//printName方法本身放入 方法区
public void printName(){
System.out.println(name);
}
}
2.用图说明上述程序执行jvm中数据状态
堆区:存放的是使用new关键字创建的类或者数组的(含成员变量);
栈区:存放的是局部变量(注:形参也是局部变量的一种)和对象的声明引用;
方法区(常量池):存放的是字符串常量,其他基本数据类型的常量,方法区包含所有的class,方法区中包含的都是在程序中永远的唯一的元素。
静态域:静态变量。
在JVM中的栈,堆,方法区的数据交互
1.代码展示
public class Test {
public static void main(String[] args) {
//创建Car类实例,开始通过JVM向内存加载
Car car1 = new Car(6, "black");
car1.show();
Car car2 = new Car(9, "write");
car2.show();
}
}
class Car{
private int num;//成员变量(堆)
private String color;//成员变量(堆)
public Car() {
}
//形参m,n为局部变量(栈)
public Car(int m, String n) {
this.num = m;
this.color = n;
}
//方法名show放到方法区
public void show(){
System.out.println("car:num-"+num+"color-"+color);
}
}
2.用图说明上述程序执行jvm中数据状态
当执行代码: Car car1 = new Car(6, “black”); 时,JVM的内存模型发生的变化是
3.总结:在堆中创建对象,对象的属性 color 和 num 赋值为默认值,而对象的引用地址0x8888存放在栈中,当调用构造函数的时候,形参m和n放到栈中,并且给对象的属性复制。执行完构造函数时,形参m和n的生命周期结束,m和n出栈。