Java创建对象时的内存分析

引言

在Java中实例化对象时,我们不可避免都要用到new关键字来创建对象。
那么在一个对象被创建出来的过程里,内存做了一些什么事情呢?
本文通过简单的java内存模型来阐述对象创建过程中内存中的变化,着重于了解在new一个对象时,内存里的行为。(注:内存模型受到了极其的简化)

1、示例代码

创建一个Dog类,实例化两个对象,分别是"AHuang"和"AHui"。

//创建Dog类,定义成员变量和run方法

public class Dog{
		String name;
		int age;
		
		public void run(){
			System.out.println("running");
		}
}

//编写测试代码

public class Test{

  public static void main(String[] args){
    Dog doggy1 = new Dog();
    doggy1.name = "Ahuang";
    doggy1.age = 1;
    doggy1.shout;

    Dog doggy2 = new Dog();
    doggy2.name = "AHui";
    doggy2.age = 5;
    doggy2.shout;
    
}
}

2、名词解释

栈:主要用于存储main(),引用变量名等

堆:存储对象

方法区:加载类相关信息

静态方法区,和类一起加载,可以被对象直接使用

3、流程图

创建对象内存分析

4、流程分析

  1. 程序运行时,首先加载一些关于Test类的模版信息,该Test类里含有
  • main()方法
  • 常量池(含AHuang,AHui等字符串)

main方法被压入栈的最底下

  1. 执行main方法,遇到Dog类,加载Dog类,内含
  • name
  • age
  • run()方法

此时name,age都没有值

  1. main方法遇到new Dog,创建对象
  • 栈内存中会为doggy1引用开辟空间

  • 堆内存中会为doggy1开辟空间,此时堆内存中的doggy1对象的成员变量被默认初始化。

  • 对象里的name值调用了常量池的“AHuang”字符串,调用了Dog类里的run()方法,完成自定义初始化。

  • 通过构造方法完成对象初始化完毕。

  • 将doggy1引用指向doggy1对象的内存。

5、总结

  • 在程序运行时,主方法所在的类Test首先在方法区内被加载,主方法里调用了Dog类,于是方法区继续加载出Dog类
  • 使用new关键字创建doggy对象时,Dog类生成了一个名为doggy1的引用类型,栈内存中被开辟了一片空间用于其存储,该引用类型不存储任何东西,只存储一个指向对象的地址。
  • 该引用类型存储指向对象的地址,并且在堆内存中开辟一片空间,即该引用类型在堆内存中加载出一个对象,此时对象的成员方法得到加载,,对象的变量如String,int都为默认初值,即完成默认初始化。
  • 方法区中Test中常量池里的值被传给对象,对象完成自定义初始化。
  • doggy2同理
posted @ 2021-09-11 12:10  全辣柯基  阅读(306)  评论(0编辑  收藏  举报