目录
3.1 JVM内存结构划分
3.2 对象内存解析
举例:
内存解析图:
面试题:对象名中存储的是什么呢?
3.3 练习
3.1 JVM内存结构划分
HotSpot Java虚拟机的架构图如下。其中我们主要关心的是运行时数据区部分(Runtime Data Area)。
其中:
堆(Heap)
:此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
栈(Stack)
:是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。
方法区(Method Area)
:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
3.2 对象内存解析
举例:
class Person { //类:人
String name;
int age;
boolean isMale;
}
public class PersonTest { //测试类
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "赵同学";
p1.age = 20;
p1.isMale = true;
Person p2 = new Person();
p2.age = 10;
Person p3 = p1;
p3.name = "郭同学";
}
}
内存解析图:
说明:
堆:凡是new出来的结构(对象、数组)都放在堆空间中。
对象的属性存放在堆空间中。
创建一个类的多个对象(比如p1、p2),则每个对象都拥有当前类的一套"副本"(即属性)。当通过一个对象修改其属性时,不会影响其它对象此属性的值。
当声明一个新的变量使用现有的对象进行赋值时(比如p3 = p1),此时并没有在堆空间中创建新的对象。而是两个变量共同指向了堆空间中同一个对象。当通过一个对象修改属性时,会影响另外一个对象对此属性的调用。
面试题:对象名中存储的是什么呢?
答:对象地址
public class StudentTest{
public static void main(String[] args){
System.out.println(new Student());//Student@7852e922
Student stu = new Student();
System.out.println(stu);//Student@4e25154f
int[] arr = new int[5];
System.out.println(arr);//[I@70dea4e
}
}
直接打印对象名和数组名都是显示“类型@对象的hashCode值",所以说类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址。
3.3 练习
根据代码,画出内存图
class Car {
String color = "red";
int num = 4;
void show() {
System.out.println("color=" + color + ",num=" + num);
}
}
class CarTest {
public static void main(String[] args) {
Car c1 = new Car(); //建立对象c1
Car c2 = new Car(); //建立对象c2
c1.color = "blue"; //对对象的属性进行修改
c1.show(); //使用对象的方法
c2.show();
}
}