- 栈内存中加载的是局部变量,也就是指虚拟机栈中局部变量表部分,具体有:编译器可知的各种数据类型(boolean、byte、char、short、int、float、long、double)以及对象引用(reference类型,它不同于对象本身,可是一个指向对象起始地址的引用指针)。
- 堆内存是Java虚拟机所管理的内存中最大的一块,Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。
- 方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。
为此针对Student类进行调用测试:
代码如下:
class Student {
private String name;
private int age;
public Student(){
}
public Student(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public void show(){
System.out.println( name + "---" + age );
}
}
此类创建了有参构造方法和无参构造方法,设置成员变量(私有),还有对应的成员方法,接下来再看一段代码:
public class Test {
public static void main(String[] args) {
Student s1 = new Student("小丽", 18);
//创建s1对象,在堆内存为 new 出来的对象开辟空间,对象的变量都有自己的默认值。
Student s2 = new Student("小明", 20);
//创建s2对象,在堆内存为 new 出来的对象开辟空间,对象的变量都有自己的默认值。
Student s3 = s1;
//创建对象s3,地址指针指向s1原来的地址,也就是为s1开辟出的内存空间,同时也指向s3。
s3.setAge(20);//调用成员方法给堆内存中s3对象的变量重新赋值;
s1.show();//调用成员方法;
s2.show();
s3.show();
}
}
具体的内存分配图如下:
- 首先在方法区加载主类字节码Test.class文件和main方法;
- 将main函数加载进栈,创建Student类对象 s1和s2;
- 在堆内存中为new出来的s1和s2,分别分配内存空间,分配相应的地址值,并将地址分别赋栈内存中的s1,s2;
- 对于s1,s2变量赋默认值(String 型为null,int 型为0);
- 创建s3时,将s1的地址值赋给s1,即与s1共享堆内存空间;
- 然后依次调用方法,执行方法,依次弹栈,弹栈顺序与进栈顺序相反;
- 需要注意:s1与s3共享堆内存空间,故而s3调用setAge()可将堆内存中s1的age值修改;
- 弹栈结束后,堆内存等待垃圾回收器回收即可;