面向对象学习笔记5 - Java中方法调用的内存解析

以下是一个简单的Java代码示例,演示对象创建、方法调用及内存存储过程:

// 1. 定义Person类
class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void displayInfo() {
        System.out.println("Name: " + name + ", Age: " + age);
    }
}

// 2. 测试类
public class Main {
    public static void main(String[] args) {
        // 3. 创建对象
        Person person = new Person("Alice", 25);
        
        // 4. 调用对象方法
        person.displayInfo();
    }
}

内存存储过程解读:

1. 类加载阶段(方法区)

• 当程序启动时:
Person.classMain.class 被加载到方法区
• 存储类的结构信息(字段、方法、构造函数等)
• 类变量和字节码指令也存储在方法区

2. 对象创建过程(堆内存)

Person person = new Person("Alice", 25);

new Person() 执行时:
• 在堆内存中分配空间(存储所有实例变量)
• 创建对象头(存储类指针、GC信息等)
• 初始化字段:name=null, age=0
• 执行构造函数进行赋值

内存结构:

堆内存
┌───────────┐
│ Person对象 │
├───────────┤
│ name      │ -> 指向字符串常量池中的"Alice"
│ age       │ = 25
└───────────┘

3. 引用变量存储(栈内存)

• 局部变量person存储在main方法的栈帧中
• 保存指向堆内存中Person对象的地址指针

内存结构:

栈内存(main方法栈帧)
┌───────────┐
│ person    │ -> 堆中Person对象的内存地址
└───────────┘

4. 方法调用过程

person.displayInfo();

• ① 创建新的栈帧(用于displayInfo方法)
• ② 隐式传入this参数(指向调用对象)
• ③ 执行方法字节码(来自方法区)
• ④ 访问堆中的name和age数据
• ⑤ 方法返回后栈帧销毁

内存结构:

栈内存
┌──────────────┐
│ displayInfo   │
├──────────────┤
│ this         │ -> 指向Person对象
└──────────────┘
↑
┌──────────────┐
│ main方法栈帧  │
└──────────────┘

5. 参数传递(字符串常量池)

• "Alice"字符串存储在字符串常量池(属于方法区)
• 当创建字符串时会复用常量池中的对象


完整生命周期

  1. 类加载 → 方法区
  2. 对象实例化 → 堆内存
  3. 方法调用 → 栈内存
  4. 引用变量 → 栈内存
  5. 方法执行 → 方法区字节码 + 栈内存操作
  6. 垃圾回收 → 当对象不再被引用时,堆内存会被GC回收

关键点总结

• 方法区:类的"蓝图"存储
• 堆内存:对象实际存储位置
• 栈内存:方法调用和局部变量
• 每个方法调用创建独立的栈帧
• this引用隐含传递对象地址
• 对象访问需要通过地址引用跳转

posted @ 2025-03-05 17:23  谁来着?  阅读(14)  评论(0)    收藏  举报