目录介绍

  • 01.首先看代码案例
  • 02.JVM加载类过程
  • 03.对构造方法赋值
  • 04.通过对象调用方法

01.首先看代码案例

  • 以下面代码为例,来分析,Java 的实例对象在内存中的空间分配。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    //JVM 启动时将 Person.class 放入方法区
    public class Person {

    //静态变量,直接放到常量池中
    public static final String number = "13667225184";

    //new Person 创建实例后,name 引用放入堆区,name 对象放入常量池
    private String name;

    //new Person 创建实例后,age = 0 放入堆区
    private int age;

    //Person 方法放入方法区,方法内代码作为 Code 属性放入方法区
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    //toString 方法放入方法区,方法内代码作为 Code 属性放入方法区
    @Override
    public String toString() {
    return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
    }

    //JVM 启动时将 Test.class 放入方法区
    public class Test {

    //main 方法放入方法区,方法内代码作为 Code 属性放入方法区
    public static void main(String[] args) {

    //person1 是引用放入虚拟机栈区,new 关键字开辟堆内存 Person 自定义对象放入堆区
    Person person1 = new Person("张三", 18);
    Person person2 = new Person("李四", 20);

    //通过 person 引用创建 toString() 方法栈帧
    person1.toString();
    person2.toString();
    }
    }

02.JVM加载类过程

  • 首先 JVM 会将 Test.class, Person.class 加载到方法区,找到有 main() 方法的类开始执行。
  • 分析步骤
    • 如上图所示,JVM 找到 main() 方法入口,创建 main() 方法的栈帧放入虚拟机栈,开始执行 main() 方法。
    • Person person1 = new Person(“张三”, 18);
    • 执行到这句代码时,JVM 会先创建 Person。实例放入堆区,person2 也同理。

03.对构造方法赋值

  • 创建完 Person 两个实例,main() 方法中的 person1,person2 会指向堆区中的 0x001,0x002(这里的内存地址仅作为示范)。紧接着会调用 Person 的构造函数进行赋值,如下图:

  • 如上图所示,新创建的的 Person 实例中的 name, age 开始都是默认值。 调用构造函数之后进行赋值,name 是 String 引用类型,会在常量池中创建并将地址赋值给 name,age 是基本数据类型将直接保存数值。

  • 注:Java 中基本类型的包装类的大部分都实现了常量池技术,这些类是 Byte, Short, Integer, Long, Character, Boolean,另外两种浮点数类型的包装类则没有实现。

    基本数据类型 包装类(是否实现了常量池技术)
    byte Byte 是
    boolean Boolean 是
    short Short 是
    char Character 是
    int Integer 是
    long Long 是
    float Float 否
    double Double 否

04.通过对象调用方法

  • Person 实例初始化完后,执行到 toString() 方法,同 main() 方法一样 JVM 会创建一个 toString() 的栈帧放入虚拟机栈中,执行完之后返回一个值。