Java 在new一个新对象的时候内存中发生了什么

java在new一个对象的时候,是经过了以下的步骤的
①首先是JVM虚拟机编译对象所在的class文件,将class文件放入方法区中
②JVM虚拟机读取main方法的入口,将main方法入栈,执行创建对象的代码,如Person p =new Person();
③在main方法所在的栈内存中分配引用 p
④在堆中分配内存,将创建的Person对象放入堆内存
⑤将栈中的引用p, 指向Person对象

以上就是创建一个对象是,内存发生了什么的具体介绍,接下来看看图解
Java 在new一个新对象的时候内存中发生了什么_栈
.
.
.
.

接下来再补充一下关于堆,栈,方法区,常量池,静态区的知识

.

堆:

堆主要存放Java在运行过程中new出来的对象,凡是通过new生成的对象都存放在堆中,对于堆中的对象生命周期的管理由Java虚拟机的垃圾回收机制GC进行回收和统一管理。类的非静态成员变量也放在堆区,其中基本数据类型是直接保存值,而复杂类型是保存指向对象的引用,非静态成员变量在类的实例化时开辟空间并且初始化。

栈:

栈主要存放在运行期间用到的一些局部变量(基本数据类型的变量)或者是指向其他对象的一些引用,因为方法执行时,被分配的内存就在栈中,所以当然存储的局部变量就在栈中咯。当一段代码或者一个方法调用完毕后,栈中为这段代码所提供的基本数据类型或者对象的引用立即被释放;

常量池:

常量池是方法区的一部分内存(此处请看文末补充)。常量池在编译期间就将一部分数据存放于该区域,包含基本数据类型如int、long等以final声明的常量值,和String字符串、特别注意的是对于方法运行期位于栈中的局部变量String常量的值可以通过 String.intern()方法将该值置入到常量池中。

需要特别注意的是:

方法区是线程安全的。由于所有的线程都共享方法区,所以,方法区里的数据访问必须被设计成线程安全的。例如,假如同时有两个线程都企图访问方法区中的同一个类,而这个类还没有被装入JVM,那么只允许一个线程去装载它,而其它线程必须等待 !

成员变量与局部变量总结:

一:在方法中声明的变量,就是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因,在方法中生明的变量可以是基本类型的变量,也可以是引用类型的变量,
(1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中
(2)当声明的是引用变量时,所声明的变量(该变量实际上在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆内存中的
二:在类中声明的变量是成员变量,也叫全局变量,放在堆中的,同样在类中声明的变量既可以是基本类型的变量 也可是引用类型的变量
(1)当声明的是基本类型的变量,其变量名及其值是放在堆内存中的
(2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象

2022年5月18日订正补充如下

ps(此文章首次发布于2020年8月)
Java 在new一个新对象的时候内存中发生了什么_局部变量_02

在《深入理解Java虚拟机》一书中,提到的是静态变量放在方法区里

然而实际上,JDK7及其以后版本的HotSpot虚拟机选择把静态变量与常量池存储于Java堆之中。

为什么会相反呢。因为《深入理解Java虚拟机》中提到的只是一个规范,是针对所有Java虚拟机的。而我们常用的HotSpot虚拟机只是众多Java虚拟机中的一个,HotSpot有自己的具体实现,不要搞混了,Java虚拟机不等于HotSpot,是包含关系。

–我是“道祖且长”,一个在互联网"苟且偷生"的Java程序员
“有任何问题,可评论,我看到就会回复”